@hoanghainh/komagu 2.5.0 → 2.6.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/CHANGELOG.md +30 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/ai-run-stats.json +87 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/auth-model.md +120 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/coverage.json +19 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-001.json +516 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-002.json +332 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-003.json +218 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-004.json +561 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-005.json +316 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-006.json +14 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/inj-injection-001.json +782 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/inj-injection-002.json +418 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/priv-privilege-001.json +627 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/priv-privilege-002.json +253 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-1.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-10.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-11.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-12.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-13.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-14.json +66 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-15.json +69 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-16.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-17.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-18.json +69 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-19.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-2.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-20.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-21.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-22.json +50 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-3.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-4.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-5.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-6.json +70 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-7.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-8.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-9.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings.json +4857 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/report.ja.md +2112 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/report.md +2112 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/score.json +82 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/ai-run-stats.json +91 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/auth-model.md +120 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/coverage.json +21 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-001.json +593 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-002.json +367 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-003.json +207 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-004.json +477 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-005.json +341 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-006.json +14 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/inj-injection-001.json +821 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/inj-injection-002.json +410 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/priv-privilege-001.json +649 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/priv-privilege-002.json +222 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-1.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-10.json +67 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-11.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-12.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-13.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-14.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-15.json +70 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-16.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-17.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-18.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-19.json +65 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-2.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-20.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-21.json +62 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-22.json +50 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-3.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-4.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-5.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-6.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-7.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-8.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-9.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings.json +4966 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/score.json +87 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/ground-truth.json +851 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/ai-run-stats.json +96 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/auth-model.md +191 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/coverage.json +31 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-001.json +527 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-002.json +568 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-003.json +467 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-004.json +342 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-005.json +693 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-006.json +16 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/inj-injection-001.json +1123 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/inj-injection-002.json +391 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/priv-privilege-001.json +726 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/priv-privilege-002.json +306 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-1.json +137 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-10.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-11.json +81 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-12.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-13.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-14.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-15.json +110 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-16.json +116 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-17.json +141 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-18.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-19.json +140 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-2.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-20.json +82 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-21.json +74 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-22.json +99 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-3.json +140 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-4.json +145 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-5.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-6.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-7.json +87 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-8.json +125 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-9.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings.json +6989 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/memory.log +36 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/score.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/auth-model.md +517 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-001.json +5 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-002.json +428 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-003.json +388 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-004.json +463 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-005.json +5 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-006.json +67 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/inj-injection-001.json +964 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings.partial.json +1872 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/memory.log +194 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/score.partial.json +108 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/stack-profile.json +225 -0
- package/assess/lsa/scripts/laravel_routes.py +102 -0
- package/assess/lsa/scripts/map_routes.py +4 -1
- package/assess/lsa/tests/EVAL-RESULTS.md +126 -0
- package/assess/lsa/tests/test_eval_run_6.py +104 -0
- package/assess/lsa/tests/test_laravel_routes.py +95 -0
- package/examples/member-portal/backend-dotnet/Auth/DemoAuthenticationHandler.cs +75 -0
- package/examples/member-portal/backend-dotnet/Program.cs +1 -72
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/Application.kt +4 -0
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/controller/Controllers.kt +3 -0
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/model/Entities.kt +4 -0
- package/examples/member-portal/tests/test_d6_demo_app.py +4 -4
- package/examples/member-portal/tests/test_d6_remediation_verification.py +6 -6
- package/operate/ai/client.py +27 -10
- package/operate/ai/runner.py +4 -2
- package/operate/cli/__init__.py +1 -1
- package/operate/cli/commands/scan.py +8 -1
- package/operate/cross_user_tester/runner.py +4 -1
- package/operate/devsecops/sbom.py +12 -4
- package/operate/simulate/scenarios.py +11 -2
- package/operate/tests/test_ai_reasoning_effort.py +65 -0
- package/operate/tests/test_ai_route_inventory.py +53 -0
- package/operate/tests/test_audit_minimum_versions.py +89 -0
- package/operate/tests/test_cli.py +1 -1
- package/operate/tests/test_scheme_and_xml_guards.py +67 -0
- package/package.json +1 -1
- package/remediate/authz/dotnet/src/Komagu.Security.Authorization/LoggingSecurityAuditSink.cs +19 -3
- package/remediate/authz/golang/authz_test.go +5 -2
- package/remediate/authz/spring/src/main/kotlin/io/komagu/security/authorization/DefaultKomaguSecurityManager.kt +74 -78
- package/remediate/authz/spring/src/main/kotlin/io/komagu/security/spring/OwnershipAspect.kt +129 -158
- package/remediate/deps/patcher.py +2 -1
- package/remediate/edge/mock-backend/app.py +2 -1
- package/remediate/edge/tests/test_edge_security.py +5 -5
- package/remediate/ekyc/requirements.txt +1 -1
- package/remediate/identity/dotnet/src/Komagu.Security.Identity/OidcServiceCollectionExtensions.cs +19 -6
- package/remediate/identity/python/requirements.txt +2 -2
- package/remediate/identity/spring/src/main/kotlin/io/komagu/security/identity/KomaguIdentityAutoConfiguration.kt +31 -38
- package/remediate/legacy_shims/tests/test_legacy_shims.py +8 -8
- package/remediate/query/dotnet/src/Komagu.Security.Query/SafeSortAllowList.cs +5 -2
- package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/SafeSortAllowList.kt +10 -11
- package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/detekt/StringBuiltSqlQueryRule.kt +19 -24
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
{
|
|
2
|
+
"batch_id": "routes-005",
|
|
3
|
+
"findings": [
|
|
4
|
+
{
|
|
5
|
+
"finding_id": "BOLA-R-0072-1",
|
|
6
|
+
"category": "bola",
|
|
7
|
+
"subtype": "missing_ownership_check",
|
|
8
|
+
"title": "User creation allows any authenticated user to create a new account (IDOR on resource ownership)",
|
|
9
|
+
"route_id": "R-0072",
|
|
10
|
+
"endpoint": {
|
|
11
|
+
"method": "POST",
|
|
12
|
+
"path": "/users"
|
|
13
|
+
},
|
|
14
|
+
"location": {
|
|
15
|
+
"file": "python-flask/profile.py",
|
|
16
|
+
"start_line": 8,
|
|
17
|
+
"end_line": 13
|
|
18
|
+
},
|
|
19
|
+
"evidence": [
|
|
20
|
+
{
|
|
21
|
+
"file": "python-flask/profile.py",
|
|
22
|
+
"line": 10,
|
|
23
|
+
"code": "user = User(**request.json)",
|
|
24
|
+
"why": "User object is constructed directly from request payload without verifying ownership or restricting fields"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"file": "python-flask/profile.py",
|
|
28
|
+
"line": 12,
|
|
29
|
+
"code": "db.session.commit()",
|
|
30
|
+
"why": "The created user is persisted immediately. No check ensures the current session user owns this new record."
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"attack_scenario": "User A sends POST /users with a JSON body containing User B's email or ID. The server creates a new user account owned by User A but potentially associated with User B's data, or simply allows User A to create an arbitrary account.",
|
|
34
|
+
"impact": "Creation of unauthorized accounts or association of resources with wrong users.",
|
|
35
|
+
"severity": "high",
|
|
36
|
+
"confidence": "high",
|
|
37
|
+
"cwe": [
|
|
38
|
+
"CWE-284",
|
|
39
|
+
"CWE-639"
|
|
40
|
+
],
|
|
41
|
+
"owasp": [
|
|
42
|
+
"API1:2023"
|
|
43
|
+
],
|
|
44
|
+
"recommendation": "Restrict the fields accepted in the request body to only those allowed for creation by the current user, or explicitly bind the created record to the authenticated user's ID before saving.",
|
|
45
|
+
"status": "unverified",
|
|
46
|
+
"attack_vector": {
|
|
47
|
+
"target_param": "id"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"finding_id": "BOLA-R-0073-1",
|
|
52
|
+
"category": "bola",
|
|
53
|
+
"subtype": "missing_ownership_check",
|
|
54
|
+
"title": "User name update allows any authenticated user to modify another user's name via ID parameter",
|
|
55
|
+
"route_id": "R-0073",
|
|
56
|
+
"endpoint": {
|
|
57
|
+
"method": "POST",
|
|
58
|
+
"path": "/users/<int:uid>/name"
|
|
59
|
+
},
|
|
60
|
+
"location": {
|
|
61
|
+
"file": "python-flask/profile.py",
|
|
62
|
+
"start_line": 16,
|
|
63
|
+
"end_line": 21
|
|
64
|
+
},
|
|
65
|
+
"evidence": [
|
|
66
|
+
{
|
|
67
|
+
"file": "python-flask/profile.py",
|
|
68
|
+
"line": 18,
|
|
69
|
+
"code": "user = User.query.get(uid)",
|
|
70
|
+
"why": "User is fetched using the ID from the URL path parameter (request-controlled), without verifying if it matches the current session user."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"file": "python-flask/profile.py",
|
|
74
|
+
"line": 19,
|
|
75
|
+
"code": "user.name = request.json[\"name\"]",
|
|
76
|
+
"why": "The name field is updated on the fetched object. If uid points to another user, their name is changed."
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"attack_scenario": "User A sends POST /users/5/name with name='Hacker'. If User 5 belongs to User B, User A successfully changes User B's name.",
|
|
80
|
+
"impact": "Modification of other users' personal data (name).",
|
|
81
|
+
"severity": "high",
|
|
82
|
+
"confidence": "high",
|
|
83
|
+
"cwe": [
|
|
84
|
+
"CWE-284",
|
|
85
|
+
"CWE-639"
|
|
86
|
+
],
|
|
87
|
+
"owasp": [
|
|
88
|
+
"API1:2023"
|
|
89
|
+
],
|
|
90
|
+
"recommendation": "Verify that the `uid` parameter matches the ID of the currently authenticated user before updating, or use a scoped query like `User.query.filter_by(id=current_user.id).get(uid)`.",
|
|
91
|
+
"status": "unverified",
|
|
92
|
+
"attack_vector": {
|
|
93
|
+
"target_param": "uid"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"finding_id": "BOLA-R-0074-1",
|
|
98
|
+
"category": "bola",
|
|
99
|
+
"subtype": "missing_ownership_check",
|
|
100
|
+
"title": "User patch allows any authenticated user to modify another user's data via ID parameter",
|
|
101
|
+
"route_id": "R-0074",
|
|
102
|
+
"endpoint": {
|
|
103
|
+
"method": "PATCH",
|
|
104
|
+
"path": "/users/<int:uid>"
|
|
105
|
+
},
|
|
106
|
+
"location": {
|
|
107
|
+
"file": "python-flask/profile.py",
|
|
108
|
+
"start_line": 24,
|
|
109
|
+
"end_line": 30
|
|
110
|
+
},
|
|
111
|
+
"evidence": [
|
|
112
|
+
{
|
|
113
|
+
"file": "python-flask/profile.py",
|
|
114
|
+
"line": 26,
|
|
115
|
+
"code": "user = User.query.get(uid)",
|
|
116
|
+
"why": "User is fetched using the ID from the URL path parameter (request-controlled), without verifying if it matches the current session user."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"file": "python-flask/profile.py",
|
|
120
|
+
"line": 27,
|
|
121
|
+
"code": "for key, value in request.json.items():",
|
|
122
|
+
"why": "All fields from the request body are updated on the fetched object. If uid points to another user, their data is overwritten."
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"attack_scenario": "User A sends PATCH /users/5 with JSON {\"email\": \"hacker@test.com\"}. If User 5 belongs to User B, User A successfully changes User B's email.",
|
|
126
|
+
"impact": "Modification of other users' sensitive data (email, password reset tokens, etc.).",
|
|
127
|
+
"severity": "high",
|
|
128
|
+
"confidence": "high",
|
|
129
|
+
"cwe": [
|
|
130
|
+
"CWE-284",
|
|
131
|
+
"CWE-639"
|
|
132
|
+
],
|
|
133
|
+
"owasp": [
|
|
134
|
+
"API1:2023"
|
|
135
|
+
],
|
|
136
|
+
"recommendation": "Verify that the `uid` parameter matches the ID of the currently authenticated user before updating, or use a scoped query like `User.query.filter_by(id=current_user.id).get(uid)`.",
|
|
137
|
+
"status": "unverified",
|
|
138
|
+
"attack_vector": {
|
|
139
|
+
"target_param": "uid"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"finding_id": "BOLA-R-0010-1",
|
|
144
|
+
"category": "bola",
|
|
145
|
+
"subtype": "missing_ownership_check",
|
|
146
|
+
"title": "Customer edit allows any authenticated user to modify another customer via model binding",
|
|
147
|
+
"route_id": "R-0010",
|
|
148
|
+
"endpoint": {
|
|
149
|
+
"method": "POST",
|
|
150
|
+
"path": "/Customer/Edit"
|
|
151
|
+
},
|
|
152
|
+
"location": {
|
|
153
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
154
|
+
"start_line": 12,
|
|
155
|
+
"end_line": 16
|
|
156
|
+
},
|
|
157
|
+
"evidence": [
|
|
158
|
+
{
|
|
159
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
160
|
+
"line": 12,
|
|
161
|
+
"code": "public ActionResult Edit(Customer customer)",
|
|
162
|
+
"why": "The `Customer` object is bound directly from the request (likely POST body or form). The ID in the model comes from the attacker's input."
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
166
|
+
"line": 14,
|
|
167
|
+
"code": "db.Entry(customer).State = System.Data.Entity.EntityState.Modified;",
|
|
168
|
+
"why": "The entity is marked as modified and saved. No check verifies if the `customer.Id` matches the current user's ID."
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"attack_scenario": "User A sends POST /Customer/Edit with a JSON/Form containing Customer B's ID and details. The server updates Customer B's record.",
|
|
172
|
+
"impact": "Modification of other customers' data.",
|
|
173
|
+
"severity": "high",
|
|
174
|
+
"confidence": "high",
|
|
175
|
+
"cwe": [
|
|
176
|
+
"CWE-284",
|
|
177
|
+
"CWE-639"
|
|
178
|
+
],
|
|
179
|
+
"owasp": [
|
|
180
|
+
"API1:2023"
|
|
181
|
+
],
|
|
182
|
+
"recommendation": "Verify that the `customer.Id` in the request matches the ID of the currently authenticated user before saving changes.",
|
|
183
|
+
"status": "unverified"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"finding_id": "BOLA-R-0011-1",
|
|
187
|
+
"category": "bola",
|
|
188
|
+
"subtype": "missing_ownership_check",
|
|
189
|
+
"title": "Customer name update allows any authenticated user to modify another customer via model binding",
|
|
190
|
+
"route_id": "R-0011",
|
|
191
|
+
"endpoint": {
|
|
192
|
+
"method": "POST",
|
|
193
|
+
"path": "/Customer/EditName"
|
|
194
|
+
},
|
|
195
|
+
"location": {
|
|
196
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
197
|
+
"start_line": 20,
|
|
198
|
+
"end_line": 23
|
|
199
|
+
},
|
|
200
|
+
"evidence": [
|
|
201
|
+
{
|
|
202
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
203
|
+
"line": 20,
|
|
204
|
+
"code": "public ActionResult EditName([Bind(Include = \"Id,Name\")] Customer customer)",
|
|
205
|
+
"why": "The `Customer` object is bound from the request. The ID comes from the attacker's input."
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
209
|
+
"line": 22,
|
|
210
|
+
"code": "db.SaveChanges();",
|
|
211
|
+
"why": "The entity is saved without verifying ownership of the `customer.Id` against the session user."
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
"attack_scenario": "User A sends POST /Customer/EditName with a JSON/Form containing Customer B's ID and new name. The server updates Customer B's name.",
|
|
215
|
+
"impact": "Modification of other customers' data (name).",
|
|
216
|
+
"severity": "high",
|
|
217
|
+
"confidence": "high",
|
|
218
|
+
"cwe": [
|
|
219
|
+
"CWE-284",
|
|
220
|
+
"CWE-639"
|
|
221
|
+
],
|
|
222
|
+
"owasp": [
|
|
223
|
+
"API1:2023"
|
|
224
|
+
],
|
|
225
|
+
"recommendation": "Verify that the `customer.Id` in the request matches the ID of the currently authenticated user before saving changes.",
|
|
226
|
+
"status": "unverified",
|
|
227
|
+
"attack_vector": {
|
|
228
|
+
"target_param": "id"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"finding_id": "BOLA-R-0012-1",
|
|
233
|
+
"category": "bola",
|
|
234
|
+
"subtype": "missing_ownership_check",
|
|
235
|
+
"title": "Customer refresh allows any authenticated user to modify another customer via ID parameter",
|
|
236
|
+
"route_id": "R-0012",
|
|
237
|
+
"endpoint": {
|
|
238
|
+
"method": "POST",
|
|
239
|
+
"path": "/Customer/Refresh"
|
|
240
|
+
},
|
|
241
|
+
"location": {
|
|
242
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
243
|
+
"start_line": 27,
|
|
244
|
+
"end_line": 32
|
|
245
|
+
},
|
|
246
|
+
"evidence": [
|
|
247
|
+
{
|
|
248
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
249
|
+
"line": 29,
|
|
250
|
+
"code": "var customer = db.Customers.Find(id);",
|
|
251
|
+
"why": "The `customer` object is fetched using the `id` parameter from the request (request-controlled), without verifying if it matches the current session user."
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"file": "dotnet-legacy/Web/Controllers/CustomerController.cs",
|
|
255
|
+
"line": 30,
|
|
256
|
+
"code": "TryUpdateModel(customer);",
|
|
257
|
+
"why": "The model is updated with data from the request. If `id` points to another user, their data is overwritten."
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
"attack_scenario": "User A sends POST /Customer/Refresh?id=<customer_id_of_user_B>. The server fetches User B's record and updates it based on form data.",
|
|
261
|
+
"impact": "Modification of other customers' data.",
|
|
262
|
+
"severity": "high",
|
|
263
|
+
"confidence": "high",
|
|
264
|
+
"cwe": [
|
|
265
|
+
"CWE-284",
|
|
266
|
+
"CWE-639"
|
|
267
|
+
],
|
|
268
|
+
"owasp": [
|
|
269
|
+
"API1:2023"
|
|
270
|
+
],
|
|
271
|
+
"recommendation": "Verify that the `id` parameter matches the ID of the currently authenticated user before updating.",
|
|
272
|
+
"status": "unverified",
|
|
273
|
+
"attack_vector": {
|
|
274
|
+
"target_param": "id"
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"finding_id": "BOLA-R-0016-1",
|
|
279
|
+
"category": "bola",
|
|
280
|
+
"subtype": "missing_ownership_check",
|
|
281
|
+
"title": "File download allows any authenticated user to download another file via file_id parameter",
|
|
282
|
+
"route_id": "R-0016",
|
|
283
|
+
"endpoint": {
|
|
284
|
+
"method": "ANY",
|
|
285
|
+
"path": "/dotnet-legacy/Web/Handlers/GetFile.ashx"
|
|
286
|
+
},
|
|
287
|
+
"location": {
|
|
288
|
+
"file": "dotnet-legacy/Web/Handlers/GetFile.ashx",
|
|
289
|
+
"start_line": 8,
|
|
290
|
+
"end_line": 10
|
|
291
|
+
},
|
|
292
|
+
"evidence": [
|
|
293
|
+
{
|
|
294
|
+
"file": "dotnet-legacy/Web/Handlers/GetFile.ashx",
|
|
295
|
+
"line": 8,
|
|
296
|
+
"code": "string fileId = context.Request.QueryString[\"file_id\"];",
|
|
297
|
+
"why": "The `fileId` is taken directly from the query string (request-controlled)."
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"file": "dotnet-legacy/Web/Handlers/GetFile.ashx",
|
|
301
|
+
"line": 10,
|
|
302
|
+
"code": "context.Response.TransmitFile(path);",
|
|
303
|
+
"why": "The file is transmitted without verifying that the current session user owns or has permission to access this specific `fileId`."
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
"attack_scenario": "User A sends GET /GetFile.ashx?file_id=<file_id_of_user_B>. The server serves User B's file.",
|
|
307
|
+
"impact": "Disclosure of other users' files.",
|
|
308
|
+
"severity": "high",
|
|
309
|
+
"confidence": "high",
|
|
310
|
+
"cwe": [
|
|
311
|
+
"CWE-284",
|
|
312
|
+
"CWE-639"
|
|
313
|
+
],
|
|
314
|
+
"owasp": [
|
|
315
|
+
"API1:2023"
|
|
316
|
+
],
|
|
317
|
+
"recommendation": "Verify that the `fileId` corresponds to a file owned by the current session user before transmitting it.",
|
|
318
|
+
"status": "unverified",
|
|
319
|
+
"attack_vector": {
|
|
320
|
+
"target_param": "file_id"
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"finding_id": "BOLA-R-0029-1",
|
|
325
|
+
"category": "bola",
|
|
326
|
+
"subtype": "missing_ownership_check",
|
|
327
|
+
"title": "Profile update allows any authenticated user to modify another account via parameter binding",
|
|
328
|
+
"route_id": "R-0029",
|
|
329
|
+
"endpoint": {
|
|
330
|
+
"method": "POST",
|
|
331
|
+
"path": "<see web.xml servlet-mapping>"
|
|
332
|
+
},
|
|
333
|
+
"location": {
|
|
334
|
+
"file": "java-legacy/src/com/acme/web/ProfileServlet.java",
|
|
335
|
+
"start_line": 10,
|
|
336
|
+
"end_line": 16
|
|
337
|
+
},
|
|
338
|
+
"evidence": [
|
|
339
|
+
{
|
|
340
|
+
"file": "java-legacy/src/com/acme/web/ProfileServlet.java",
|
|
341
|
+
"line": 10,
|
|
342
|
+
"code": "Account account = new Account();",
|
|
343
|
+
"why": "A new Account object is instantiated."
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"file": "java-legacy/src/com/acme/web/ProfileServlet.java",
|
|
347
|
+
"line": 12,
|
|
348
|
+
"code": "BeanUtils.populate(account, request.getParameterMap());",
|
|
349
|
+
"why": "All parameters from the request are bound to the `account` object. The ID (if present) comes from the attacker's input."
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"file": "java-legacy/src/com/acme/web/ProfileServlet.java",
|
|
353
|
+
"line": 16,
|
|
354
|
+
"code": "// Implicitly saved or returned without ownership check in snippet",
|
|
355
|
+
"why": "The code snippet ends before a save, but `BeanUtils.populate` on an object containing an ID from the request is inherently vulnerable to IDOR if that object is subsequently persisted."
|
|
356
|
+
}
|
|
357
|
+
],
|
|
358
|
+
"attack_scenario": "User A sends POST with parameters including `id=<account_id_of_user_B>` and other fields. The server populates User B's account data.",
|
|
359
|
+
"impact": "Modification of other users' accounts.",
|
|
360
|
+
"severity": "high",
|
|
361
|
+
"confidence": "high",
|
|
362
|
+
"cwe": [
|
|
363
|
+
"CWE-284",
|
|
364
|
+
"CWE-639"
|
|
365
|
+
],
|
|
366
|
+
"owasp": [
|
|
367
|
+
"API1:2023"
|
|
368
|
+
],
|
|
369
|
+
"recommendation": "Verify that the `account.Id` in the populated object matches the ID of the currently authenticated user before saving.",
|
|
370
|
+
"status": "unverified",
|
|
371
|
+
"attack_vector": {
|
|
372
|
+
"target_param": "id"
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"finding_id": "BOLA-R-0039-1",
|
|
377
|
+
"category": "bola",
|
|
378
|
+
"subtype": "missing_ownership_check",
|
|
379
|
+
"title": "Profile update allows any authenticated user to modify their own profile (Safe for self, but IDOR if ID is passed)",
|
|
380
|
+
"route_id": "R-0039",
|
|
381
|
+
"endpoint": {
|
|
382
|
+
"method": "PUT",
|
|
383
|
+
"path": "/profile"
|
|
384
|
+
},
|
|
385
|
+
"location": {
|
|
386
|
+
"file": "node-express/routes/profile.js",
|
|
387
|
+
"start_line": 7,
|
|
388
|
+
"end_line": 9
|
|
389
|
+
},
|
|
390
|
+
"evidence": [
|
|
391
|
+
{
|
|
392
|
+
"file": "node-express/routes/profile.js",
|
|
393
|
+
"line": 8,
|
|
394
|
+
"code": "User.findByIdAndUpdate(req.user._id, req.body, ...)",
|
|
395
|
+
"why": "The query uses `req.user._id` (server-side identity) to find the user. However, if the route is intended to be generic and accepts an ID in the body, it might be vulnerable. But here, the ID is hardcoded from `req.user._id`. This is SAFE for self-modification."
|
|
396
|
+
}
|
|
397
|
+
],
|
|
398
|
+
"attack_scenario": "N/A - The code explicitly uses `req.user._id` as the lookup key.",
|
|
399
|
+
"impact": "None (Safe).",
|
|
400
|
+
"severity": "low",
|
|
401
|
+
"confidence": "high",
|
|
402
|
+
"cwe": [
|
|
403
|
+
"CWE-284"
|
|
404
|
+
],
|
|
405
|
+
"owasp": [],
|
|
406
|
+
"recommendation": "No fix needed. The code correctly binds the update to the authenticated user's ID.",
|
|
407
|
+
"status": "unverified",
|
|
408
|
+
"attack_vector": {
|
|
409
|
+
"target_param": "id"
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"finding_id": "BOLA-R-0040-1",
|
|
414
|
+
"category": "bola",
|
|
415
|
+
"subtype": "missing_ownership_check",
|
|
416
|
+
"title": "Profile name update allows any authenticated user to modify their own profile (Safe for self, but IDOR if ID is passed)",
|
|
417
|
+
"route_id": "R-0040",
|
|
418
|
+
"endpoint": {
|
|
419
|
+
"method": "PUT",
|
|
420
|
+
"path": "/profile/name"
|
|
421
|
+
},
|
|
422
|
+
"location": {
|
|
423
|
+
"file": "node-express/routes/profile.js",
|
|
424
|
+
"start_line": 11,
|
|
425
|
+
"end_line": 13
|
|
426
|
+
},
|
|
427
|
+
"evidence": [
|
|
428
|
+
{
|
|
429
|
+
"file": "node-express/routes/profile.js",
|
|
430
|
+
"line": 12,
|
|
431
|
+
"code": "User.findByIdAndUpdate(req.user._id, { name: req.body.name }, ...)",
|
|
432
|
+
"why": "The query uses `req.user._id` (server-side identity) to find the user. This is SAFE for self-modification."
|
|
433
|
+
}
|
|
434
|
+
],
|
|
435
|
+
"attack_scenario": "N/A - The code explicitly uses `req.user._id` as the lookup key.",
|
|
436
|
+
"impact": "None (Safe).",
|
|
437
|
+
"severity": "low",
|
|
438
|
+
"confidence": "high",
|
|
439
|
+
"cwe": [
|
|
440
|
+
"CWE-284"
|
|
441
|
+
],
|
|
442
|
+
"owasp": [],
|
|
443
|
+
"recommendation": "No fix needed. The code correctly binds the update to the authenticated user's ID.",
|
|
444
|
+
"status": "unverified"
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"finding_id": "BOLA-R-0041-1",
|
|
448
|
+
"category": "bola",
|
|
449
|
+
"subtype": "no_authentication",
|
|
450
|
+
"title": "Signup endpoint accepts requests without verifying authentication status (though not IDOR, it's a critical auth flaw)",
|
|
451
|
+
"route_id": "R-0041",
|
|
452
|
+
"endpoint": {
|
|
453
|
+
"method": "POST",
|
|
454
|
+
"path": "/signup"
|
|
455
|
+
},
|
|
456
|
+
"location": {
|
|
457
|
+
"file": "node-express/routes/profile.js",
|
|
458
|
+
"start_line": 15,
|
|
459
|
+
"end_line": 18
|
|
460
|
+
},
|
|
461
|
+
"evidence": [
|
|
462
|
+
{
|
|
463
|
+
"file": "node-express/routes/profile.js",
|
|
464
|
+
"line": 15,
|
|
465
|
+
"code": "router.post('/signup', function (req, res) {",
|
|
466
|
+
"why": "The route handler does not include the `ensureLoggedIn` middleware."
|
|
467
|
+
}
|
|
468
|
+
],
|
|
469
|
+
"attack_scenario": "Any user (including unauthenticated) can call this endpoint.",
|
|
470
|
+
"impact": "Account creation bypass or manipulation.",
|
|
471
|
+
"severity": "high",
|
|
472
|
+
"confidence": "high",
|
|
473
|
+
"cwe": [
|
|
474
|
+
"CWE-306"
|
|
475
|
+
],
|
|
476
|
+
"owasp": [
|
|
477
|
+
"API1:2023"
|
|
478
|
+
],
|
|
479
|
+
"recommendation": "Add the `ensureLoggedIn` middleware if signup requires auth, or ensure it is public but secure against injection.",
|
|
480
|
+
"status": "unverified",
|
|
481
|
+
"attack_vector": {
|
|
482
|
+
"target_param": "id"
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"finding_id": "BOLA-R-0042-1",
|
|
487
|
+
"category": "bola",
|
|
488
|
+
"subtype": "missing_ownership_check",
|
|
489
|
+
"title": "Profile settings update allows any authenticated user to modify their own profile (Safe for self, but IDOR if ID is passed)",
|
|
490
|
+
"route_id": "R-0042",
|
|
491
|
+
"endpoint": {
|
|
492
|
+
"method": "POST",
|
|
493
|
+
"path": "/profile/settings"
|
|
494
|
+
},
|
|
495
|
+
"location": {
|
|
496
|
+
"file": "node-express/routes/profile.js",
|
|
497
|
+
"start_line": 20,
|
|
498
|
+
"end_line": 23
|
|
499
|
+
},
|
|
500
|
+
"evidence": [
|
|
501
|
+
{
|
|
502
|
+
"file": "node-express/routes/profile.js",
|
|
503
|
+
"line": 21,
|
|
504
|
+
"code": "var prefs = Object.assign({}, req.user.prefs, { theme: req.body.theme });",
|
|
505
|
+
"why": "The code uses `req.user.prefs` (server-side identity) to construct the object. This is SAFE for self-modification."
|
|
506
|
+
}
|
|
507
|
+
],
|
|
508
|
+
"attack_scenario": "N/A - The code explicitly uses `req.user.prefs` as the base.",
|
|
509
|
+
"impact": "None (Safe).",
|
|
510
|
+
"severity": "low",
|
|
511
|
+
"confidence": "high",
|
|
512
|
+
"cwe": [
|
|
513
|
+
"CWE-284"
|
|
514
|
+
],
|
|
515
|
+
"owasp": [],
|
|
516
|
+
"recommendation": "No fix needed. The code correctly binds the update to the authenticated user's data.",
|
|
517
|
+
"status": "unverified"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
"finding_id": "BOLA-R-0063-1",
|
|
521
|
+
"category": "bola",
|
|
522
|
+
"subtype": "missing_ownership_check",
|
|
523
|
+
"title": "Profile update allows any authenticated user to modify their own profile (Safe for self, but IDOR if ID is passed)",
|
|
524
|
+
"route_id": "R-0063",
|
|
525
|
+
"endpoint": {
|
|
526
|
+
"method": "POST",
|
|
527
|
+
"path": "/php-plain/profile.php"
|
|
528
|
+
},
|
|
529
|
+
"location": {
|
|
530
|
+
"file": "php-plain/profile.php",
|
|
531
|
+
"start_line": 5,
|
|
532
|
+
"end_line": 11
|
|
533
|
+
},
|
|
534
|
+
"evidence": [
|
|
535
|
+
{
|
|
536
|
+
"file": "php-plain/profile.php",
|
|
537
|
+
"line": 5,
|
|
538
|
+
"code": "$user = load_user($_SESSION['uid']);",
|
|
539
|
+
"why": "The user is loaded using `$_SESSION['uid']` (server-side identity). This is SAFE for self-modification."
|
|
540
|
+
}
|
|
541
|
+
],
|
|
542
|
+
"attack_scenario": "N/A - The code explicitly uses `$_SESSION['uid']` to identify the user.",
|
|
543
|
+
"impact": "None (Safe).",
|
|
544
|
+
"severity": "low",
|
|
545
|
+
"confidence": "high",
|
|
546
|
+
"cwe": [
|
|
547
|
+
"CWE-284"
|
|
548
|
+
],
|
|
549
|
+
"owasp": [],
|
|
550
|
+
"recommendation": "No fix needed. The code correctly binds the update to the authenticated user's ID.",
|
|
551
|
+
"status": "unverified"
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"finding_id": "BOLA-R-0068-1",
|
|
555
|
+
"category": "bola",
|
|
556
|
+
"subtype": "missing_role_check",
|
|
557
|
+
"title": "Admin settings update allows any authenticated user to modify global settings (Missing role check)",
|
|
558
|
+
"route_id": "R-0068",
|
|
559
|
+
"endpoint": {
|
|
560
|
+
"method": "POST",
|
|
561
|
+
"path": "/php-plain/admin/settings.php"
|
|
562
|
+
},
|
|
563
|
+
"location": {
|
|
564
|
+
"file": "php-plain/admin/settings.php",
|
|
565
|
+
"start_line": 5,
|
|
566
|
+
"end_line": 10
|
|
567
|
+
},
|
|
568
|
+
"evidence": [
|
|
569
|
+
{
|
|
570
|
+
"file": "php-plain/admin/settings.php",
|
|
571
|
+
"line": 5,
|
|
572
|
+
"code": "if ($_SESSION['role'] !== 'admin') { ... exit; }",
|
|
573
|
+
"why": "The code checks if the session role is 'admin'. If not, it exits. This prevents non-admins from accessing."
|
|
574
|
+
}
|
|
575
|
+
],
|
|
576
|
+
"attack_scenario": "N/A - The code explicitly checks for admin role.",
|
|
577
|
+
"impact": "None (Safe).",
|
|
578
|
+
"severity": "low",
|
|
579
|
+
"confidence": "high",
|
|
580
|
+
"cwe": [
|
|
581
|
+
"CWE-284"
|
|
582
|
+
],
|
|
583
|
+
"owasp": [],
|
|
584
|
+
"recommendation": "No fix needed. The code correctly enforces the admin role requirement.",
|
|
585
|
+
"status": "unverified"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"finding_id": "BOLA-R-0060-1",
|
|
589
|
+
"category": "bola",
|
|
590
|
+
"subtype": "missing_ownership_check",
|
|
591
|
+
"title": "Member lookup allows any authenticated user to search for members by login/pass (Missing ownership check)",
|
|
592
|
+
"route_id": "R-0060",
|
|
593
|
+
"endpoint": {
|
|
594
|
+
"method": "GET",
|
|
595
|
+
"path": "/php-plain/mongo_find.php"
|
|
596
|
+
},
|
|
597
|
+
"location": {
|
|
598
|
+
"file": "php-plain/mongo_find.php",
|
|
599
|
+
"start_line": 5,
|
|
600
|
+
"end_line": 6
|
|
601
|
+
},
|
|
602
|
+
"evidence": [
|
|
603
|
+
{
|
|
604
|
+
"file": "php-plain/mongo_find.php",
|
|
605
|
+
"line": 5,
|
|
606
|
+
"code": "$doc = $coll->findOne(array('login' => $_GET['login'], 'pass' => $_GET['pass']));",
|
|
607
|
+
"why": "The query uses `$_GET['login']` and `$_GET['pass']` (request-controlled) to find a member. No check verifies if the current session user owns this member."
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"file": "php-plain/mongo_find.php",
|
|
611
|
+
"line": 6,
|
|
612
|
+
"code": "$docs = $coll->find(array('$where' => \"this.name == '\" . $_GET['n'] . \"'));",
|
|
613
|
+
"why": "The second query also uses `$_GET['n']` (request-controlled) to find members by name. No ownership check."
|
|
614
|
+
}
|
|
615
|
+
],
|
|
616
|
+
"attack_scenario": "User A sends GET /mongo_find.php?login=<user_b_login>&pass=<user_b_pass>. The server returns User B's account details.",
|
|
617
|
+
"impact": "Disclosure of other users' credentials and personal data.",
|
|
618
|
+
"severity": "high",
|
|
619
|
+
"confidence": "high",
|
|
620
|
+
"cwe": [
|
|
621
|
+
"CWE-284",
|
|
622
|
+
"CWE-639"
|
|
623
|
+
],
|
|
624
|
+
"owasp": [
|
|
625
|
+
"API1:2023"
|
|
626
|
+
],
|
|
627
|
+
"recommendation": "Verify that the found member's ID matches the ID of the currently authenticated user before returning the data.",
|
|
628
|
+
"status": "unverified"
|
|
629
|
+
}
|
|
630
|
+
],
|
|
631
|
+
"route_verdicts": [
|
|
632
|
+
{
|
|
633
|
+
"route_id": "R-0072",
|
|
634
|
+
"verdict": "vulnerable"
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
"route_id": "R-0073",
|
|
638
|
+
"verdict": "vulnerable"
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"route_id": "R-0074",
|
|
642
|
+
"verdict": "vulnerable"
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
"route_id": "R-0010",
|
|
646
|
+
"verdict": "vulnerable"
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
"route_id": "R-0011",
|
|
650
|
+
"verdict": "vulnerable"
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"route_id": "R-0012",
|
|
654
|
+
"verdict": "vulnerable"
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
"route_id": "R-0016",
|
|
658
|
+
"verdict": "vulnerable"
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"route_id": "R-0029",
|
|
662
|
+
"verdict": "vulnerable"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"route_id": "R-0039",
|
|
666
|
+
"verdict": "safe"
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"route_id": "R-0040",
|
|
670
|
+
"verdict": "safe"
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
"route_id": "R-0041",
|
|
674
|
+
"verdict": "vulnerable"
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
"route_id": "R-0042",
|
|
678
|
+
"verdict": "safe"
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
"route_id": "R-0063",
|
|
682
|
+
"verdict": "safe"
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
"route_id": "R-0068",
|
|
686
|
+
"verdict": "safe"
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
"route_id": "R-0060",
|
|
690
|
+
"verdict": "vulnerable"
|
|
691
|
+
}
|
|
692
|
+
]
|
|
693
|
+
}
|