diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..2b51ab46 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,28 @@ +## Goal + + +## Changes + +- +- +- + +## Testing + +- [ ] Application runs locally +- [ ] Commands executed successfully +- [ ] Documentation reviewed for accuracy + +## Artifacts & Screenshots + +- Screenshots: + - + - + +--- + +### Checklist +- [ ] PR title is clear and descriptive +- [ ] Documentation updated (if applicable) +- [ ] No secrets, credentials, or large temporary files committed + diff --git a/labs/lab2/baseline/data-asset-diagram.png b/labs/lab2/baseline/data-asset-diagram.png new file mode 100644 index 00000000..4457d768 Binary files /dev/null and b/labs/lab2/baseline/data-asset-diagram.png differ diff --git a/labs/lab2/baseline/data-flow-diagram.png b/labs/lab2/baseline/data-flow-diagram.png new file mode 100644 index 00000000..a8803816 Binary files /dev/null and b/labs/lab2/baseline/data-flow-diagram.png differ diff --git a/labs/lab2/baseline/report.pdf b/labs/lab2/baseline/report.pdf new file mode 100644 index 00000000..369376fe Binary files /dev/null and b/labs/lab2/baseline/report.pdf differ diff --git a/labs/lab2/baseline/risks.json b/labs/lab2/baseline/risks.json new file mode 100644 index 00000000..7e917d5d --- /dev/null +++ b/labs/lab2/baseline/risks.json @@ -0,0 +1,410 @@ +[ + { + "category": "missing-hardening", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 3, + "exploitation_impact": 1, + "title": "Missing Hardening risk at Juice Shop Application", + "synthetic_id": "missing-hardening@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "missing-hardening", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 3, + "exploitation_impact": 1, + "title": "Missing Hardening risk at Persistent Storage", + "synthetic_id": "missing-hardening@persistent-storage", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "persistent-storage", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "persistent-storage" + ] + }, + { + "category": "missing-build-infrastructure", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Missing Build Infrastructure in the threat model (referencing asset Juice Shop Application as an example)", + "synthetic_id": "missing-build-infrastructure@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [] + }, + { + "category": "server-side-request-forgery", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 3, + "exploitation_impact": 1, + "title": "Server-Side Request Forgery (SSRF) risk at Juice Shop Application server-side web-requesting the target Webhook Endpoint via To Challenge WebHook", + "synthetic_id": "server-side-request-forgery@juice-shop@webhook-endpoint@juice-shop>to-challenge-webhook", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "juice-shop>to-challenge-webhook", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "server-side-request-forgery", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 3, + "exploitation_impact": 1, + "title": "Server-Side Request Forgery (SSRF) risk at Reverse Proxy server-side web-requesting the target Juice Shop Application via To App", + "synthetic_id": "server-side-request-forgery@reverse-proxy@juice-shop@reverse-proxy>to-app", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "reverse-proxy", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "reverse-proxy>to-app", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "reverse-proxy" + ] + }, + { + "category": "unnecessary-data-transfer", + "risk_status": "unchecked", + "severity": 1, + "exploitation_likelihood": 1, + "exploitation_impact": 1, + "title": "Unnecessary Data Transfer of Tokens & Sessions data at User Browser from/to Juice Shop Application", + "synthetic_id": "unnecessary-data-transfer@tokens-sessions@user-browser@juice-shop", + "most_relevant_data_asset": "tokens-sessions", + "most_relevant_technical_asset": "user-browser", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "user-browser" + ] + }, + { + "category": "unnecessary-data-transfer", + "risk_status": "unchecked", + "severity": 1, + "exploitation_likelihood": 1, + "exploitation_impact": 1, + "title": "Unnecessary Data Transfer of Tokens & Sessions data at User Browser from/to Reverse Proxy", + "synthetic_id": "unnecessary-data-transfer@tokens-sessions@user-browser@reverse-proxy", + "most_relevant_data_asset": "tokens-sessions", + "most_relevant_technical_asset": "user-browser", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "user-browser" + ] + }, + { + "category": "unnecessary-technical-asset", + "risk_status": "unchecked", + "severity": 1, + "exploitation_likelihood": 1, + "exploitation_impact": 1, + "title": "Unnecessary Technical Asset named Persistent Storage", + "synthetic_id": "unnecessary-technical-asset@persistent-storage", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "persistent-storage", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "persistent-storage" + ] + }, + { + "category": "unnecessary-technical-asset", + "risk_status": "unchecked", + "severity": 1, + "exploitation_likelihood": 1, + "exploitation_impact": 1, + "title": "Unnecessary Technical Asset named User Browser", + "synthetic_id": "unnecessary-technical-asset@user-browser", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "user-browser", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "user-browser" + ] + }, + { + "category": "cross-site-scripting", + "risk_status": "unchecked", + "severity": 4, + "exploitation_likelihood": 3, + "exploitation_impact": 2, + "title": "Cross-Site Scripting (XSS) risk at Juice Shop Application", + "synthetic_id": "cross-site-scripting@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "cross-site-request-forgery", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 4, + "exploitation_impact": 1, + "title": "Cross-Site Request Forgery (CSRF) risk at Juice Shop Application via Direct to App (no proxy) from User Browser", + "synthetic_id": "cross-site-request-forgery@juice-shop@user-browser>direct-to-app-no-proxy", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "cross-site-request-forgery", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 4, + "exploitation_impact": 1, + "title": "Cross-Site Request Forgery (CSRF) risk at Juice Shop Application via To App from Reverse Proxy", + "synthetic_id": "cross-site-request-forgery@juice-shop@reverse-proxy>to-app", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "reverse-proxy>to-app", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "missing-waf", + "risk_status": "unchecked", + "severity": 1, + "exploitation_likelihood": 1, + "exploitation_impact": 1, + "title": "Missing Web Application Firewall (WAF) risk at Juice Shop Application", + "synthetic_id": "missing-waf@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "unencrypted-communication", + "risk_status": "unchecked", + "severity": 4, + "exploitation_likelihood": 3, + "exploitation_impact": 3, + "title": "Unencrypted Communication named Direct to App (no proxy) between User Browser and Juice Shop Application transferring authentication data (like credentials, token, session-id, etc.)", + "synthetic_id": "unencrypted-communication@user-browser>direct-to-app-no-proxy@user-browser@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "user-browser", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "unencrypted-communication", + "risk_status": "unchecked", + "severity": 4, + "exploitation_likelihood": 3, + "exploitation_impact": 2, + "title": "Unencrypted Communication named To App between Reverse Proxy and Juice Shop Application", + "synthetic_id": "unencrypted-communication@reverse-proxy>to-app@reverse-proxy@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "reverse-proxy", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "reverse-proxy>to-app", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "missing-authentication", + "risk_status": "unchecked", + "severity": 4, + "exploitation_likelihood": 3, + "exploitation_impact": 2, + "title": "Missing Authentication covering communication link To App from Reverse Proxy to Juice Shop Application", + "synthetic_id": "missing-authentication@reverse-proxy>to-app@reverse-proxy@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "reverse-proxy>to-app", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "missing-authentication-second-factor", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Missing Two-Factor Authentication covering communication link Direct to App (no proxy) from User Browser to Juice Shop Application", + "synthetic_id": "missing-authentication-second-factor@user-browser>direct-to-app-no-proxy@user-browser@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "missing-authentication-second-factor", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Missing Two-Factor Authentication covering communication link To App from User Browser forwarded via Reverse Proxy to Juice Shop Application", + "synthetic_id": "missing-authentication-second-factor@reverse-proxy>to-app@reverse-proxy@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "reverse-proxy>to-app", + "data_breach_probability": 2, + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "container-baseimage-backdooring", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Container Base Image Backdooring risk at Juice Shop Application", + "synthetic_id": "container-baseimage-backdooring@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "probable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "unencrypted-asset", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Unencrypted Technical Asset named Juice Shop Application", + "synthetic_id": "unencrypted-asset@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "juice-shop" + ] + }, + { + "category": "unencrypted-asset", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Unencrypted Technical Asset named Persistent Storage", + "synthetic_id": "unencrypted-asset@persistent-storage", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "persistent-storage", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [ + "persistent-storage" + ] + }, + { + "category": "missing-vault", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Missing Vault (Secret Storage) in the threat model (referencing asset Juice Shop Application as an example)", + "synthetic_id": "missing-vault@juice-shop", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "juice-shop", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [] + }, + { + "category": "missing-identity-store", + "risk_status": "unchecked", + "severity": 2, + "exploitation_likelihood": 1, + "exploitation_impact": 2, + "title": "Missing Identity Store in the threat model (referencing asset Reverse Proxy as an example)", + "synthetic_id": "missing-identity-store@reverse-proxy", + "most_relevant_data_asset": "", + "most_relevant_technical_asset": "reverse-proxy", + "most_relevant_trust_boundary": "", + "most_relevant_shared_runtime": "", + "most_relevant_communication_link": "", + "data_breach_probability": "improbable", + "data_breach_technical_assets": [] + } +] diff --git a/labs/lab2/baseline/stats.json b/labs/lab2/baseline/stats.json new file mode 100644 index 00000000..88cd78be --- /dev/null +++ b/labs/lab2/baseline/stats.json @@ -0,0 +1 @@ +{"risks":{"critical":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"elevated":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":4},"high":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"low":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":5},"medium":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":14}}} \ No newline at end of file diff --git a/labs/lab2/baseline/technical-assets.json b/labs/lab2/baseline/technical-assets.json new file mode 100644 index 00000000..45457f1e --- /dev/null +++ b/labs/lab2/baseline/technical-assets.json @@ -0,0 +1 @@ +{"juice-shop":{"Id":"juice-shop","Title":"Juice Shop Application","Description":"OWASP Juice Shop server (Node.js/Express, v19.0.0).","Usage":0,"Type":1,"Size":2,"Technology":6,"Machine":2,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":true,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"In-scope web application (contains all business logic and vulnerabilities by design).","Tags":["app","nodejs"],"DataAssetsProcessed":["user-accounts","orders","product-catalog","tokens-sessions"],"DataAssetsStored":["logs"],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"juice-shop\u003eto-challenge-webhook","SourceId":"juice-shop","TargetId":"webhook-endpoint","Title":"To Challenge WebHook","Description":"Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved.","Protocol":2,"Tags":["egress"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["orders"],"DataAssetsReceived":null,"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":70.02881844380403},"persistent-storage":{"Id":"persistent-storage","Title":"Persistent Storage","Description":"Host-mounted volume for database, file uploads, and logs.","Usage":1,"Type":2,"Size":3,"Technology":10,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs).","Tags":["storage","volume"],"DataAssetsProcessed":[],"DataAssetsStored":["logs","user-accounts","orders","product-catalog"],"DataFormatsAccepted":[3],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":100},"reverse-proxy":{"Id":"reverse-proxy","Title":"Reverse Proxy","Description":"Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers.","Usage":0,"Type":1,"Size":2,"Technology":20,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Not exposed to internet directly; improves security of inbound traffic.","Tags":["optional","proxy"],"DataAssetsProcessed":["product-catalog","tokens-sessions"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"reverse-proxy\u003eto-app","SourceId":"reverse-proxy","TargetId":"juice-shop","Title":"To App","Description":"Proxy forwarding to app (HTTP on 3000 internally).","Protocol":1,"Tags":[],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":9.623538157950035},"user-browser":{"Id":"user-browser","Title":"User Browser","Description":"End-user web browser (client).","Usage":0,"Type":0,"Size":0,"Technology":2,"Machine":1,"Internet":true,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":true,"Encryption":0,"JustificationOutOfScope":"","Owner":"External User","Confidentiality":0,"Integrity":1,"Availability":1,"JustificationCiaRating":"Client controlled by end user (potentially an attacker).","Tags":["actor","user"],"DataAssetsProcessed":[],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"user-browser\u003eto-reverse-proxy-preferred","SourceId":"user-browser","TargetId":"reverse-proxy","Title":"To Reverse Proxy (preferred)","Description":"User browser to reverse proxy (HTTPS on 443).","Protocol":2,"Tags":["primary"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true},{"Id":"user-browser\u003edirect-to-app-no-proxy","SourceId":"user-browser","TargetId":"juice-shop","Title":"Direct to App (no proxy)","Description":"Direct browser access to app (HTTP on 3000).","Protocol":1,"Tags":["direct"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":25.859639506459924},"webhook-endpoint":{"Id":"webhook-endpoint","Title":"Webhook Endpoint","Description":"External WebHook service (3rd-party, if configured for integrations).","Usage":0,"Type":0,"Size":0,"Technology":14,"Machine":1,"Internet":true,"MultiTenant":true,"Redundant":true,"CustomDevelopedParts":false,"OutOfScope":true,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"Third-party service to receive notifications (not under our control).","Owner":"Third-Party","Confidentiality":1,"Integrity":1,"Availability":1,"JustificationCiaRating":"External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured.","Tags":["saas","webhook"],"DataAssetsProcessed":["orders"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":1}} \ No newline at end of file diff --git a/labs/lab2/secure/data-asset-diagram.png b/labs/lab2/secure/data-asset-diagram.png new file mode 100644 index 00000000..aacf4016 Binary files /dev/null and b/labs/lab2/secure/data-asset-diagram.png differ diff --git a/labs/lab2/secure/data-flow-diagram.png b/labs/lab2/secure/data-flow-diagram.png new file mode 100644 index 00000000..5ead09e2 Binary files /dev/null and b/labs/lab2/secure/data-flow-diagram.png differ diff --git a/labs/lab2/secure/report.pdf b/labs/lab2/secure/report.pdf new file mode 100644 index 00000000..66ddc3f2 Binary files /dev/null and b/labs/lab2/secure/report.pdf differ diff --git a/labs/lab2/secure/risks.json b/labs/lab2/secure/risks.json new file mode 100644 index 00000000..0988f32e --- /dev/null +++ b/labs/lab2/secure/risks.json @@ -0,0 +1 @@ +[{"category":"missing-authentication","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Authentication\u003c/b\u003e covering communication link \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eReverse Proxy\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication@reverse-proxy\u003eto-app@reverse-proxy@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"unnecessary-data-transfer","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Data Transfer\u003c/b\u003e of \u003cb\u003eTokens \u0026 Sessions\u003c/b\u003e data at \u003cb\u003eUser Browser\u003c/b\u003e from/to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"unnecessary-data-transfer@tokens-sessions@user-browser@juice-shop","most_relevant_data_asset":"tokens-sessions","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"unnecessary-data-transfer","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Data Transfer\u003c/b\u003e of \u003cb\u003eTokens \u0026 Sessions\u003c/b\u003e data at \u003cb\u003eUser Browser\u003c/b\u003e from/to \u003cb\u003eReverse Proxy\u003c/b\u003e","synthetic_id":"unnecessary-data-transfer@tokens-sessions@user-browser@reverse-proxy","most_relevant_data_asset":"tokens-sessions","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"missing-waf","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eMissing Web Application Firewall (WAF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-waf@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"missing-identity-store","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Identity Store\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eReverse Proxy\u003c/b\u003e as an example)","synthetic_id":"missing-identity-store@reverse-proxy","most_relevant_data_asset":"","most_relevant_technical_asset":"reverse-proxy","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"missing-authentication-second-factor","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Two-Factor Authentication\u003c/b\u003e covering communication link \u003cb\u003eDirect to App (no proxy)\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication-second-factor@user-browser\u003edirect-to-app-no-proxy@user-browser@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"user-browser\u003edirect-to-app-no-proxy","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"missing-authentication-second-factor","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Two-Factor Authentication\u003c/b\u003e covering communication link \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e forwarded via \u003cb\u003eReverse Proxy\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication-second-factor@reverse-proxy\u003eto-app@reverse-proxy@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"container-baseimage-backdooring","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eContainer Base Image Backdooring\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"container-baseimage-backdooring@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"probable","data_breach_technical_assets":["juice-shop"]},{"category":"unnecessary-technical-asset","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Technical Asset\u003c/b\u003e named \u003cb\u003ePersistent Storage\u003c/b\u003e","synthetic_id":"unnecessary-technical-asset@persistent-storage","most_relevant_data_asset":"","most_relevant_technical_asset":"persistent-storage","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["persistent-storage"]},{"category":"unnecessary-technical-asset","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Technical Asset\u003c/b\u003e named \u003cb\u003eUser Browser\u003c/b\u003e","synthetic_id":"unnecessary-technical-asset@user-browser","most_relevant_data_asset":"","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"cross-site-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"very-likely","exploitation_impact":"low","title":"\u003cb\u003eCross-Site Request Forgery (CSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eDirect to App (no proxy)\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e","synthetic_id":"cross-site-request-forgery@juice-shop@user-browser\u003edirect-to-app-no-proxy","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"user-browser\u003edirect-to-app-no-proxy","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"cross-site-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"very-likely","exploitation_impact":"low","title":"\u003cb\u003eCross-Site Request Forgery (CSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eReverse Proxy\u003c/b\u003e","synthetic_id":"cross-site-request-forgery@juice-shop@reverse-proxy\u003eto-app","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"missing-build-infrastructure","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Build Infrastructure\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eJuice Shop Application\u003c/b\u003e as an example)","synthetic_id":"missing-build-infrastructure@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"missing-vault","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Vault (Secret Storage)\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eJuice Shop Application\u003c/b\u003e as an example)","synthetic_id":"missing-vault@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"unencrypted-asset","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eUnencrypted Technical Asset\u003c/b\u003e named \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"unencrypted-asset@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"cross-site-scripting","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"medium","title":"\u003cb\u003eCross-Site Scripting (XSS)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"cross-site-scripting@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"server-side-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eServer-Side Request Forgery (SSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e server-side web-requesting the target \u003cb\u003eWebhook Endpoint\u003c/b\u003e via \u003cb\u003eTo Challenge WebHook\u003c/b\u003e","synthetic_id":"server-side-request-forgery@juice-shop@webhook-endpoint@juice-shop\u003eto-challenge-webhook","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"juice-shop\u003eto-challenge-webhook","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"server-side-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eServer-Side Request Forgery (SSRF)\u003c/b\u003e risk at \u003cb\u003eReverse Proxy\u003c/b\u003e server-side web-requesting the target \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eTo App\u003c/b\u003e","synthetic_id":"server-side-request-forgery@reverse-proxy@juice-shop@reverse-proxy\u003eto-app","most_relevant_data_asset":"","most_relevant_technical_asset":"reverse-proxy","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["reverse-proxy"]},{"category":"missing-hardening","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eMissing Hardening\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-hardening@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"missing-hardening","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eMissing Hardening\u003c/b\u003e risk at \u003cb\u003ePersistent Storage\u003c/b\u003e","synthetic_id":"missing-hardening@persistent-storage","most_relevant_data_asset":"","most_relevant_technical_asset":"persistent-storage","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["persistent-storage"]}] \ No newline at end of file diff --git a/labs/lab2/secure/stats.json b/labs/lab2/secure/stats.json new file mode 100644 index 00000000..c19a18a6 --- /dev/null +++ b/labs/lab2/secure/stats.json @@ -0,0 +1 @@ +{"risks":{"critical":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"elevated":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":2},"high":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"low":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":5},"medium":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":13}}} \ No newline at end of file diff --git a/labs/lab2/secure/technical-assets.json b/labs/lab2/secure/technical-assets.json new file mode 100644 index 00000000..a082acb4 --- /dev/null +++ b/labs/lab2/secure/technical-assets.json @@ -0,0 +1 @@ +{"juice-shop":{"Id":"juice-shop","Title":"Juice Shop Application","Description":"OWASP Juice Shop server (Node.js/Express, v19.0.0).","Usage":0,"Type":1,"Size":2,"Technology":6,"Machine":2,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":true,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"In-scope web application (contains all business logic and vulnerabilities by design).","Tags":["app","nodejs"],"DataAssetsProcessed":["user-accounts","orders","product-catalog","tokens-sessions"],"DataAssetsStored":["logs"],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"juice-shop\u003eto-challenge-webhook","SourceId":"juice-shop","TargetId":"webhook-endpoint","Title":"To Challenge WebHook","Description":"Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved.","Protocol":2,"Tags":["egress"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["orders"],"DataAssetsReceived":null,"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":70.02881844380403},"persistent-storage":{"Id":"persistent-storage","Title":"Persistent Storage","Description":"Host-mounted volume for database, file uploads, and logs.","Usage":1,"Type":2,"Size":3,"Technology":10,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs).","Tags":["storage","volume"],"DataAssetsProcessed":[],"DataAssetsStored":["logs","user-accounts","orders","product-catalog"],"DataFormatsAccepted":[3],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":100},"reverse-proxy":{"Id":"reverse-proxy","Title":"Reverse Proxy","Description":"Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers.","Usage":0,"Type":1,"Size":2,"Technology":20,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Not exposed to internet directly; improves security of inbound traffic.","Tags":["optional","proxy"],"DataAssetsProcessed":["product-catalog","tokens-sessions"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"reverse-proxy\u003eto-app","SourceId":"reverse-proxy","TargetId":"juice-shop","Title":"To App","Description":"Proxy forwarding to app (HTTP on 3000 internally).","Protocol":2,"Tags":[],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":9.623538157950035},"user-browser":{"Id":"user-browser","Title":"User Browser","Description":"End-user web browser (client).","Usage":0,"Type":0,"Size":0,"Technology":2,"Machine":1,"Internet":true,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":true,"Encryption":0,"JustificationOutOfScope":"","Owner":"External User","Confidentiality":0,"Integrity":1,"Availability":1,"JustificationCiaRating":"Client controlled by end user (potentially an attacker).","Tags":["actor","user"],"DataAssetsProcessed":[],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"user-browser\u003eto-reverse-proxy-preferred","SourceId":"user-browser","TargetId":"reverse-proxy","Title":"To Reverse Proxy (preferred)","Description":"User browser to reverse proxy (HTTPS on 443).","Protocol":2,"Tags":["primary"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true},{"Id":"user-browser\u003edirect-to-app-no-proxy","SourceId":"user-browser","TargetId":"juice-shop","Title":"Direct to App (no proxy)","Description":"Direct browser access to app (HTTP on 3000).","Protocol":2,"Tags":["direct"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":25.859639506459924},"webhook-endpoint":{"Id":"webhook-endpoint","Title":"Webhook Endpoint","Description":"External WebHook service (3rd-party, if configured for integrations).","Usage":0,"Type":0,"Size":0,"Technology":14,"Machine":1,"Internet":true,"MultiTenant":true,"Redundant":true,"CustomDevelopedParts":false,"OutOfScope":true,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"Third-party service to receive notifications (not under our control).","Owner":"Third-Party","Confidentiality":1,"Integrity":1,"Availability":1,"JustificationCiaRating":"External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured.","Tags":["saas","webhook"],"DataAssetsProcessed":["orders"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":1}} \ 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 00000000..4bfdf2fd --- /dev/null +++ b/labs/lab2/threagile-model.secure.yaml @@ -0,0 +1,429 @@ +threagile_version: 1.0.0 + +title: OWASP Juice Shop — Local Lab Threat Model +date: 2025-02-16 + +author: + name: Daniel Gevorgyan + 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: 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; 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)." + 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 + 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: 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: {} + + 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/labs/lab2/threagile-model.yaml b/labs/lab2/threagile-model.yaml index 85c01a79..a6092993 100644 --- a/labs/lab2/threagile-model.yaml +++ b/labs/lab2/threagile-model.yaml @@ -1,10 +1,10 @@ threagile_version: 1.0.0 title: OWASP Juice Shop — Local Lab Threat Model -date: 2025-09-18 +date: 2025-02-16 author: - name: Student Name + name: Daniel Gevorgyan homepage: https://example.edu management_summary_comment: > diff --git a/labs/submission1.md b/labs/submission1.md new file mode 100644 index 00000000..dbb1ccc3 --- /dev/null +++ b/labs/submission1.md @@ -0,0 +1,41 @@ +# Triage Report — OWASP Juice Shop + +## Scope & Asset +- Asset: OWASP Juice Shop (local lab instance) +- Image: bkimminich/juice-shop:v19.0.0 +- Release link/date: +- Image digest (optional): + +## Environment +- Host OS: NixOS 26.05 (Yarara) x86_64 +- Docker: 29.1.5 + +## Deployment Details +- Run command used: `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v19.0.0` +- Access URL: http://127.0.0.1:3000 +- Network exposure: 127.0.0.1 only [x] Yes [ ] No + +## Health Check +- Page load: ![Page load](./submission1/page-load.png) +- API check: first 5–10 lines from `curl -s http://127.0.0.1:3000/rest/products | head` + +## Surface Snapshot (Triage) +- Login/Registration visible: [x] Yes [ ] No — notes: Login is visible under Account button on a page header +- Product listing/search present: [x] Yes [ ] No — notes: Products are displayed +- Admin or account area discoverable: [x] Yes [ ] No +- Client-side errors in console: [ ] Yes [x] No — notes: no errors are leaked +- Security headers (quick look — optional): `curl -I http://127.0.0.1:3000` → CSP/HSTS present? notes: Basic security headers present but missing CSP and HSTS headers + +## Risks Observed (Top 3) +1) Missing Content Security Policy (CSP) -- + Application lacks CSP headers, making it vulnerable to XSS attacks as there are no restrictions on script sources or inline execution. +2) No HTTP Strict Transport Security (HSTS) -- + Absence of HSTS headers leaves the application susceptible to SSL stripping attacks and protocol downgrades. +3) Exposed Admin Interface -- + Administrative endpoints are discoverable without proper rate limiting or multi-factor authentication, potentially allowing brute force attacks. + + +## GitHub Community + +Starring repositories helps signal project quality and usefulness, supports maintainers through visible appreciation, and improves discoverability of valuable open-source tools. Following developers makes it easier to track relevant work, learn from others’ approaches, and build professional connections that support effective collaboration and long-term career growth. + diff --git a/labs/submission1/page-load.png b/labs/submission1/page-load.png new file mode 100644 index 00000000..af73e664 Binary files /dev/null and b/labs/submission1/page-load.png differ diff --git a/labs/submission2.md b/labs/submission2.md new file mode 100644 index 00000000..40510b3a --- /dev/null +++ b/labs/submission2.md @@ -0,0 +1,136 @@ +# Lab 2 — Threat Modeling with Threagile + +## Overview + +This submission documents the threat modeling of the OWASP Juice Shop (`bkimminich/juice-shop:v19.0.0`) using Threagile. +The lab includes a baseline threat model, a secure HTTPS variant, and a comparative risk analysis demonstrating how security controls affect the risk landscape. + +--- + +## Task 1 — Threagile Baseline Model + +### Baseline Model Generation + +- Threagile was executed using the provided YAML model: + - Model file: `lab2/threagile-model.yaml` + - Output directory: `lab2/baseline/` +- The Docker-based Threagile run successfully generated: + - `report.pdf` + - Risk data (`risks.json`, `stats.json`, `technical-assets.json`) + - Data-flow and asset diagrams (PNG) + +### Generated Artifacts + +- PDF Report: `lab2/baseline/report.pdf` +- Diagrams: + - Data Flow Diagram: `lab2/baseline/data-flow-diagram.png` + - Data Asset Diagram: `lab2/baseline/data-asset-diagram.png` +- Risk Export: `lab2/baseline/risks.json` + +--- + +### Risk Ranking Methodology + +Risks were ranked using a composite score calculated as follows: + +``` +Composite Score = Severity × 100 + Likelihood × 10 + Impact +``` + +**Scoring values used:** + +| Dimension | Values | +|-----------|--------| +| Severity | critical (5), elevated (4), high (3), medium (2), low (1) | +| Likelihood| very-likely (4), likely (3), possible (2), unlikely (1) | +| Impact | high (3), medium (2), low (1) | + +The Top 5 risks were selected based on the highest composite scores. + +--- + +### Top 5 Risks (Baseline) + +| Rank | Risk Title | Category | Asset | Severity | Likelihood | Impact | Composite Score | +|-----:|------------------------------------|-----------------------------|-------------|--------------|-------------|----------|-----------------| +| 1 | Unencrypted Communicatin | unencrypted-communication | Application | elevated (4) | likely (3) | high (3) | 433 | +| 2 | Missing Authentication | missing-authentication | Application | elevated (4) | likely (3) | high (3) | 432 | +| 3 | Cross-Site Scripting (XSS) | cross-site-scripting | Application | elevated (4) | likely (3) | high (3) | 432 | +| 4 | Cross-Site Request Forgery (CSRF) | cross-site-request-forgery | Application | high (3) | likely (3) | high (3) | 241 | +| 5 | Server-Side Request Forgery (SSRF) | server-side-request-forgery | Application | high (3) | possible (2)| high (3) | 231 | + +--- + +### Baseline Risk Analysis + +The baseline threat model highlights several critical application-layer risks. Unencrypted communication represents the highest risk due to the potential for credential leakage and data interception. Authentication-related weaknesses and common web vulnerabilities such as XSS and CSRF further increase the attack surface, particularly in a deliberately vulnerable application like OWASP Juice Shop. SSRF remains a concern due to its potential to access internal resources. + +--- + +## Task 2 — Secure HTTPS Variant & Risk Comparison + +### Secure Model Changes + +A secure variant of the baseline model was created at: `lab2/threagile-model.secure.yaml` + +The following changes were applied: + +- Communication between **User Browser → Application** set to `protocol: https` +- Communication involving the **Reverse Proxy** set to `protocol: https` +- **Persistent Storage** configured with `encryption: transparent` + +No asset names or architectural structure were changed to ensure accurate risk comparison. + +--- + +### Secure Variant Generation + +- Output directory: `lab2/secure/` +- Generated artifacts: + - `report.pdf` + - Updated diagrams + - Updated `risks.json` + +--- + +### Risk Category Delta Table + +The following table compares the number of risks per category between the baseline and secure models: + +| Category | Baseline | Secure | Δ | +|---|---:|---:|---:| +| container-baseimage-backdooring | 1 | 1 | 0 | +| cross-site-request-forgery | 2 | 2 | 0 | +| cross-site-scripting | 1 | 1 | 0 | +| missing-authentication | 1 | 1 | 0 | +| missing-authentication-second-factor | 2 | 2 | 0 | +| missing-build-infrastructure | 1 | 1 | 0 | +| missing-hardening | 2 | 2 | 0 | +| missing-identity-store | 1 | 1 | 0 | +| missing-vault | 1 | 1 | 0 | +| missing-waf | 1 | 1 | 0 | +| server-side-request-forgery | 2 | 2 | 0 | +| unencrypted-asset | 2 | 1 | -1 | +| unencrypted-communication | 2 | 0 | -2 | +| unnecessary-data-transfer | 2 | 2 | 0 | +| unnecessary-technical-asset | 2 | 2 | 0 | + +--- + +### Delta Analysis + +The baseline threat model highlights several critical application-layer risks. Unencrypted communication represents the highest risk due to the potential for credential leakage and data interception. Authentication-related weaknesses and common web vulnerabilities such as XSS and CSRF further increase the attack surface, particularly in a deliberately vulnerable application like OWASP Juice Shop. SSRF remains a concern due to its potential to access internal resources. + +--- + +### Diagram Comparison +- Baseline Diagrams: `lab2/baseline/data-flow-diagram.png`, `lab2/baseline/data-asset-diagram.png` +- Secure Diagram: `lab2/secure/data-flow-diagram.png`, `lab2/baseline/data-asset-diagram.png` + +The data-flow diagram reflects the transition to HTTPS, while the data-asset diagram remains unchanged, as encryption at rest does not alter asset relationships. + +--- + +## Conclusion + +This lab demonstrates how threat modeling as code enables systematic evaluation of security controls. Introducing HTTPS and encryption at rest significantly reduced transport and storage-related risks while leaving application-layer vulnerabilities unchanged. This highlights the importance of layered defenses and complementary controls when securing web applications.