@etcsec-com/etc-collector 1.4.0
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/.env.example +60 -0
- package/.env.test.example +33 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/release.yml +246 -0
- package/.prettierrc.json +10 -0
- package/CHANGELOG.md +15 -0
- package/Dockerfile +57 -0
- package/LICENSE +190 -0
- package/README.md +194 -0
- package/dist/api/controllers/audit.controller.d.ts +21 -0
- package/dist/api/controllers/audit.controller.d.ts.map +1 -0
- package/dist/api/controllers/audit.controller.js +179 -0
- package/dist/api/controllers/audit.controller.js.map +1 -0
- package/dist/api/controllers/auth.controller.d.ts +16 -0
- package/dist/api/controllers/auth.controller.d.ts.map +1 -0
- package/dist/api/controllers/auth.controller.js +146 -0
- package/dist/api/controllers/auth.controller.js.map +1 -0
- package/dist/api/controllers/export.controller.d.ts +27 -0
- package/dist/api/controllers/export.controller.d.ts.map +1 -0
- package/dist/api/controllers/export.controller.js +80 -0
- package/dist/api/controllers/export.controller.js.map +1 -0
- package/dist/api/controllers/health.controller.d.ts +5 -0
- package/dist/api/controllers/health.controller.d.ts.map +1 -0
- package/dist/api/controllers/health.controller.js +16 -0
- package/dist/api/controllers/health.controller.js.map +1 -0
- package/dist/api/controllers/jobs.controller.d.ts +13 -0
- package/dist/api/controllers/jobs.controller.d.ts.map +1 -0
- package/dist/api/controllers/jobs.controller.js +125 -0
- package/dist/api/controllers/jobs.controller.js.map +1 -0
- package/dist/api/controllers/providers.controller.d.ts +15 -0
- package/dist/api/controllers/providers.controller.d.ts.map +1 -0
- package/dist/api/controllers/providers.controller.js +112 -0
- package/dist/api/controllers/providers.controller.js.map +1 -0
- package/dist/api/dto/AuditRequest.dto.d.ts +6 -0
- package/dist/api/dto/AuditRequest.dto.d.ts.map +1 -0
- package/dist/api/dto/AuditRequest.dto.js +3 -0
- package/dist/api/dto/AuditRequest.dto.js.map +1 -0
- package/dist/api/dto/AuditResponse.dto.d.ts +17 -0
- package/dist/api/dto/AuditResponse.dto.d.ts.map +1 -0
- package/dist/api/dto/AuditResponse.dto.js +3 -0
- package/dist/api/dto/AuditResponse.dto.js.map +1 -0
- package/dist/api/dto/TokenRequest.dto.d.ts +6 -0
- package/dist/api/dto/TokenRequest.dto.d.ts.map +1 -0
- package/dist/api/dto/TokenRequest.dto.js +3 -0
- package/dist/api/dto/TokenRequest.dto.js.map +1 -0
- package/dist/api/dto/TokenResponse.dto.d.ts +12 -0
- package/dist/api/dto/TokenResponse.dto.d.ts.map +1 -0
- package/dist/api/dto/TokenResponse.dto.js +3 -0
- package/dist/api/dto/TokenResponse.dto.js.map +1 -0
- package/dist/api/middlewares/authenticate.d.ts +12 -0
- package/dist/api/middlewares/authenticate.d.ts.map +1 -0
- package/dist/api/middlewares/authenticate.js +141 -0
- package/dist/api/middlewares/authenticate.js.map +1 -0
- package/dist/api/middlewares/errorHandler.d.ts +3 -0
- package/dist/api/middlewares/errorHandler.d.ts.map +1 -0
- package/dist/api/middlewares/errorHandler.js +30 -0
- package/dist/api/middlewares/errorHandler.js.map +1 -0
- package/dist/api/middlewares/rateLimit.d.ts +3 -0
- package/dist/api/middlewares/rateLimit.d.ts.map +1 -0
- package/dist/api/middlewares/rateLimit.js +34 -0
- package/dist/api/middlewares/rateLimit.js.map +1 -0
- package/dist/api/middlewares/validate.d.ts +4 -0
- package/dist/api/middlewares/validate.d.ts.map +1 -0
- package/dist/api/middlewares/validate.js +31 -0
- package/dist/api/middlewares/validate.js.map +1 -0
- package/dist/api/routes/audit.routes.d.ts +5 -0
- package/dist/api/routes/audit.routes.d.ts.map +1 -0
- package/dist/api/routes/audit.routes.js +24 -0
- package/dist/api/routes/audit.routes.js.map +1 -0
- package/dist/api/routes/auth.routes.d.ts +6 -0
- package/dist/api/routes/auth.routes.d.ts.map +1 -0
- package/dist/api/routes/auth.routes.js +22 -0
- package/dist/api/routes/auth.routes.js.map +1 -0
- package/dist/api/routes/export.routes.d.ts +5 -0
- package/dist/api/routes/export.routes.d.ts.map +1 -0
- package/dist/api/routes/export.routes.js +16 -0
- package/dist/api/routes/export.routes.js.map +1 -0
- package/dist/api/routes/health.routes.d.ts +4 -0
- package/dist/api/routes/health.routes.d.ts.map +1 -0
- package/dist/api/routes/health.routes.js +11 -0
- package/dist/api/routes/health.routes.js.map +1 -0
- package/dist/api/routes/index.d.ts +10 -0
- package/dist/api/routes/index.d.ts.map +1 -0
- package/dist/api/routes/index.js +20 -0
- package/dist/api/routes/index.js.map +1 -0
- package/dist/api/routes/providers.routes.d.ts +5 -0
- package/dist/api/routes/providers.routes.d.ts.map +1 -0
- package/dist/api/routes/providers.routes.js +13 -0
- package/dist/api/routes/providers.routes.js.map +1 -0
- package/dist/api/validators/audit.schemas.d.ts +60 -0
- package/dist/api/validators/audit.schemas.d.ts.map +1 -0
- package/dist/api/validators/audit.schemas.js +55 -0
- package/dist/api/validators/audit.schemas.js.map +1 -0
- package/dist/api/validators/auth.schemas.d.ts +17 -0
- package/dist/api/validators/auth.schemas.d.ts.map +1 -0
- package/dist/api/validators/auth.schemas.js +21 -0
- package/dist/api/validators/auth.schemas.js.map +1 -0
- package/dist/app.d.ts +3 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +62 -0
- package/dist/app.js.map +1 -0
- package/dist/config/config.schema.d.ts +65 -0
- package/dist/config/config.schema.d.ts.map +1 -0
- package/dist/config/config.schema.js +95 -0
- package/dist/config/config.schema.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +75 -0
- package/dist/config/index.js.map +1 -0
- package/dist/container.d.ts +47 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +137 -0
- package/dist/container.js.map +1 -0
- package/dist/data/database.d.ts +13 -0
- package/dist/data/database.d.ts.map +1 -0
- package/dist/data/database.js +68 -0
- package/dist/data/database.js.map +1 -0
- package/dist/data/jobs/token-cleanup.job.d.ts +23 -0
- package/dist/data/jobs/token-cleanup.job.d.ts.map +1 -0
- package/dist/data/jobs/token-cleanup.job.js +96 -0
- package/dist/data/jobs/token-cleanup.job.js.map +1 -0
- package/dist/data/migrations/migration.runner.d.ts +13 -0
- package/dist/data/migrations/migration.runner.d.ts.map +1 -0
- package/dist/data/migrations/migration.runner.js +136 -0
- package/dist/data/migrations/migration.runner.js.map +1 -0
- package/dist/data/models/Token.model.d.ts +30 -0
- package/dist/data/models/Token.model.d.ts.map +1 -0
- package/dist/data/models/Token.model.js +3 -0
- package/dist/data/models/Token.model.js.map +1 -0
- package/dist/data/repositories/token.repository.d.ts +16 -0
- package/dist/data/repositories/token.repository.d.ts.map +1 -0
- package/dist/data/repositories/token.repository.js +97 -0
- package/dist/data/repositories/token.repository.js.map +1 -0
- package/dist/providers/azure/auth.provider.d.ts +5 -0
- package/dist/providers/azure/auth.provider.d.ts.map +1 -0
- package/dist/providers/azure/auth.provider.js +13 -0
- package/dist/providers/azure/auth.provider.js.map +1 -0
- package/dist/providers/azure/azure-errors.d.ts +40 -0
- package/dist/providers/azure/azure-errors.d.ts.map +1 -0
- package/dist/providers/azure/azure-errors.js +121 -0
- package/dist/providers/azure/azure-errors.js.map +1 -0
- package/dist/providers/azure/azure-retry.d.ts +41 -0
- package/dist/providers/azure/azure-retry.d.ts.map +1 -0
- package/dist/providers/azure/azure-retry.js +85 -0
- package/dist/providers/azure/azure-retry.js.map +1 -0
- package/dist/providers/azure/graph-client.d.ts +26 -0
- package/dist/providers/azure/graph-client.d.ts.map +1 -0
- package/dist/providers/azure/graph-client.js +146 -0
- package/dist/providers/azure/graph-client.js.map +1 -0
- package/dist/providers/azure/graph.provider.d.ts +23 -0
- package/dist/providers/azure/graph.provider.d.ts.map +1 -0
- package/dist/providers/azure/graph.provider.js +161 -0
- package/dist/providers/azure/graph.provider.js.map +1 -0
- package/dist/providers/azure/queries/app.queries.d.ts +6 -0
- package/dist/providers/azure/queries/app.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/app.queries.js +9 -0
- package/dist/providers/azure/queries/app.queries.js.map +1 -0
- package/dist/providers/azure/queries/policy.queries.d.ts +6 -0
- package/dist/providers/azure/queries/policy.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/policy.queries.js +9 -0
- package/dist/providers/azure/queries/policy.queries.js.map +1 -0
- package/dist/providers/azure/queries/user.queries.d.ts +7 -0
- package/dist/providers/azure/queries/user.queries.d.ts.map +1 -0
- package/dist/providers/azure/queries/user.queries.js +10 -0
- package/dist/providers/azure/queries/user.queries.js.map +1 -0
- package/dist/providers/interfaces/IGraphProvider.d.ts +31 -0
- package/dist/providers/interfaces/IGraphProvider.d.ts.map +1 -0
- package/dist/providers/interfaces/IGraphProvider.js +3 -0
- package/dist/providers/interfaces/IGraphProvider.js.map +1 -0
- package/dist/providers/interfaces/ILDAPProvider.d.ts +37 -0
- package/dist/providers/interfaces/ILDAPProvider.d.ts.map +1 -0
- package/dist/providers/interfaces/ILDAPProvider.js +3 -0
- package/dist/providers/interfaces/ILDAPProvider.js.map +1 -0
- package/dist/providers/ldap/acl-parser.d.ts +8 -0
- package/dist/providers/ldap/acl-parser.d.ts.map +1 -0
- package/dist/providers/ldap/acl-parser.js +157 -0
- package/dist/providers/ldap/acl-parser.js.map +1 -0
- package/dist/providers/ldap/ad-mappers.d.ts +8 -0
- package/dist/providers/ldap/ad-mappers.d.ts.map +1 -0
- package/dist/providers/ldap/ad-mappers.js +162 -0
- package/dist/providers/ldap/ad-mappers.js.map +1 -0
- package/dist/providers/ldap/ldap-client.d.ts +33 -0
- package/dist/providers/ldap/ldap-client.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-client.js +195 -0
- package/dist/providers/ldap/ldap-client.js.map +1 -0
- package/dist/providers/ldap/ldap-errors.d.ts +48 -0
- package/dist/providers/ldap/ldap-errors.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-errors.js +120 -0
- package/dist/providers/ldap/ldap-errors.js.map +1 -0
- package/dist/providers/ldap/ldap-retry.d.ts +14 -0
- package/dist/providers/ldap/ldap-retry.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-retry.js +102 -0
- package/dist/providers/ldap/ldap-retry.js.map +1 -0
- package/dist/providers/ldap/ldap-sanitizer.d.ts +12 -0
- package/dist/providers/ldap/ldap-sanitizer.d.ts.map +1 -0
- package/dist/providers/ldap/ldap-sanitizer.js +104 -0
- package/dist/providers/ldap/ldap-sanitizer.js.map +1 -0
- package/dist/providers/ldap/ldap.provider.d.ts +21 -0
- package/dist/providers/ldap/ldap.provider.d.ts.map +1 -0
- package/dist/providers/ldap/ldap.provider.js +165 -0
- package/dist/providers/ldap/ldap.provider.js.map +1 -0
- package/dist/providers/ldap/queries/computer.queries.d.ts +6 -0
- package/dist/providers/ldap/queries/computer.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/computer.queries.js +9 -0
- package/dist/providers/ldap/queries/computer.queries.js.map +1 -0
- package/dist/providers/ldap/queries/group.queries.d.ts +6 -0
- package/dist/providers/ldap/queries/group.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/group.queries.js +9 -0
- package/dist/providers/ldap/queries/group.queries.js.map +1 -0
- package/dist/providers/ldap/queries/user.queries.d.ts +7 -0
- package/dist/providers/ldap/queries/user.queries.d.ts.map +1 -0
- package/dist/providers/ldap/queries/user.queries.js +10 -0
- package/dist/providers/ldap/queries/user.queries.js.map +1 -0
- package/dist/providers/smb/smb.provider.d.ts +68 -0
- package/dist/providers/smb/smb.provider.d.ts.map +1 -0
- package/dist/providers/smb/smb.provider.js +382 -0
- package/dist/providers/smb/smb.provider.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +44 -0
- package/dist/server.js.map +1 -0
- package/dist/services/audit/ad-audit.service.d.ts +70 -0
- package/dist/services/audit/ad-audit.service.d.ts.map +1 -0
- package/dist/services/audit/ad-audit.service.js +1019 -0
- package/dist/services/audit/ad-audit.service.js.map +1 -0
- package/dist/services/audit/attack-graph.service.d.ts +62 -0
- package/dist/services/audit/attack-graph.service.d.ts.map +1 -0
- package/dist/services/audit/attack-graph.service.js +702 -0
- package/dist/services/audit/attack-graph.service.js.map +1 -0
- package/dist/services/audit/audit.service.d.ts +4 -0
- package/dist/services/audit/audit.service.d.ts.map +1 -0
- package/dist/services/audit/audit.service.js +10 -0
- package/dist/services/audit/audit.service.js.map +1 -0
- package/dist/services/audit/azure-audit.service.d.ts +37 -0
- package/dist/services/audit/azure-audit.service.d.ts.map +1 -0
- package/dist/services/audit/azure-audit.service.js +153 -0
- package/dist/services/audit/azure-audit.service.js.map +1 -0
- package/dist/services/audit/detectors/ad/accounts.detector.d.ts +37 -0
- package/dist/services/audit/detectors/ad/accounts.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/accounts.detector.js +881 -0
- package/dist/services/audit/detectors/ad/accounts.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/adcs.detector.d.ts +21 -0
- package/dist/services/audit/detectors/ad/adcs.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/adcs.detector.js +227 -0
- package/dist/services/audit/detectors/ad/adcs.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/advanced.detector.d.ts +63 -0
- package/dist/services/audit/detectors/ad/advanced.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/advanced.detector.js +867 -0
- package/dist/services/audit/detectors/ad/advanced.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts +16 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.js +369 -0
- package/dist/services/audit/detectors/ad/attack-paths.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/compliance.detector.d.ts +28 -0
- package/dist/services/audit/detectors/ad/compliance.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/compliance.detector.js +896 -0
- package/dist/services/audit/detectors/ad/compliance.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/computers.detector.d.ts +30 -0
- package/dist/services/audit/detectors/ad/computers.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/computers.detector.js +799 -0
- package/dist/services/audit/detectors/ad/computers.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/gpo.detector.d.ts +17 -0
- package/dist/services/audit/detectors/ad/gpo.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/gpo.detector.js +257 -0
- package/dist/services/audit/detectors/ad/gpo.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/groups.detector.d.ts +19 -0
- package/dist/services/audit/detectors/ad/groups.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/groups.detector.js +488 -0
- package/dist/services/audit/detectors/ad/groups.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/index.d.ts +15 -0
- package/dist/services/audit/detectors/ad/index.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/index.js +51 -0
- package/dist/services/audit/detectors/ad/index.js.map +1 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.d.ts +17 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.js +293 -0
- package/dist/services/audit/detectors/ad/kerberos.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.d.ts +23 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.js +328 -0
- package/dist/services/audit/detectors/ad/monitoring.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/network.detector.d.ts +39 -0
- package/dist/services/audit/detectors/ad/network.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/network.detector.js +257 -0
- package/dist/services/audit/detectors/ad/network.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/password.detector.d.ts +14 -0
- package/dist/services/audit/detectors/ad/password.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/password.detector.js +235 -0
- package/dist/services/audit/detectors/ad/password.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/permissions.detector.d.ts +20 -0
- package/dist/services/audit/detectors/ad/permissions.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/permissions.detector.js +392 -0
- package/dist/services/audit/detectors/ad/permissions.detector.js.map +1 -0
- package/dist/services/audit/detectors/ad/trusts.detector.d.ts +11 -0
- package/dist/services/audit/detectors/ad/trusts.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/ad/trusts.detector.js +186 -0
- package/dist/services/audit/detectors/ad/trusts.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/app-security.detector.d.ts +11 -0
- package/dist/services/audit/detectors/azure/app-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/app-security.detector.js +184 -0
- package/dist/services/audit/detectors/azure/app-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts +10 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.js +130 -0
- package/dist/services/audit/detectors/azure/conditional-access.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts +8 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.js +113 -0
- package/dist/services/audit/detectors/azure/privilege-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/azure/user-security.detector.d.ts +14 -0
- package/dist/services/audit/detectors/azure/user-security.detector.d.ts.map +1 -0
- package/dist/services/audit/detectors/azure/user-security.detector.js +198 -0
- package/dist/services/audit/detectors/azure/user-security.detector.js.map +1 -0
- package/dist/services/audit/detectors/index.d.ts +2 -0
- package/dist/services/audit/detectors/index.d.ts.map +1 -0
- package/dist/services/audit/detectors/index.js +38 -0
- package/dist/services/audit/detectors/index.js.map +1 -0
- package/dist/services/audit/response-formatter.d.ts +176 -0
- package/dist/services/audit/response-formatter.d.ts.map +1 -0
- package/dist/services/audit/response-formatter.js +240 -0
- package/dist/services/audit/response-formatter.js.map +1 -0
- package/dist/services/audit/scoring.service.d.ts +15 -0
- package/dist/services/audit/scoring.service.d.ts.map +1 -0
- package/dist/services/audit/scoring.service.js +139 -0
- package/dist/services/audit/scoring.service.js.map +1 -0
- package/dist/services/auth/crypto.service.d.ts +19 -0
- package/dist/services/auth/crypto.service.d.ts.map +1 -0
- package/dist/services/auth/crypto.service.js +135 -0
- package/dist/services/auth/crypto.service.js.map +1 -0
- package/dist/services/auth/errors.d.ts +19 -0
- package/dist/services/auth/errors.d.ts.map +1 -0
- package/dist/services/auth/errors.js +46 -0
- package/dist/services/auth/errors.js.map +1 -0
- package/dist/services/auth/token.service.d.ts +41 -0
- package/dist/services/auth/token.service.d.ts.map +1 -0
- package/dist/services/auth/token.service.js +208 -0
- package/dist/services/auth/token.service.js.map +1 -0
- package/dist/services/config/config.service.d.ts +6 -0
- package/dist/services/config/config.service.d.ts.map +1 -0
- package/dist/services/config/config.service.js +64 -0
- package/dist/services/config/config.service.js.map +1 -0
- package/dist/services/export/export.service.d.ts +28 -0
- package/dist/services/export/export.service.d.ts.map +1 -0
- package/dist/services/export/export.service.js +28 -0
- package/dist/services/export/export.service.js.map +1 -0
- package/dist/services/export/formatters/csv.formatter.d.ts +8 -0
- package/dist/services/export/formatters/csv.formatter.d.ts.map +1 -0
- package/dist/services/export/formatters/csv.formatter.js +46 -0
- package/dist/services/export/formatters/csv.formatter.js.map +1 -0
- package/dist/services/export/formatters/json.formatter.d.ts +40 -0
- package/dist/services/export/formatters/json.formatter.d.ts.map +1 -0
- package/dist/services/export/formatters/json.formatter.js +58 -0
- package/dist/services/export/formatters/json.formatter.js.map +1 -0
- package/dist/services/jobs/azure-job-runner.d.ts +38 -0
- package/dist/services/jobs/azure-job-runner.d.ts.map +1 -0
- package/dist/services/jobs/azure-job-runner.js +199 -0
- package/dist/services/jobs/azure-job-runner.js.map +1 -0
- package/dist/services/jobs/index.d.ts +4 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +20 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/jobs/job-runner.d.ts +64 -0
- package/dist/services/jobs/job-runner.d.ts.map +1 -0
- package/dist/services/jobs/job-runner.js +952 -0
- package/dist/services/jobs/job-runner.js.map +1 -0
- package/dist/services/jobs/job-store.d.ts +27 -0
- package/dist/services/jobs/job-store.d.ts.map +1 -0
- package/dist/services/jobs/job-store.js +261 -0
- package/dist/services/jobs/job-store.js.map +1 -0
- package/dist/services/jobs/job.types.d.ts +67 -0
- package/dist/services/jobs/job.types.d.ts.map +1 -0
- package/dist/services/jobs/job.types.js +36 -0
- package/dist/services/jobs/job.types.js.map +1 -0
- package/dist/types/ad.types.d.ts +74 -0
- package/dist/types/ad.types.d.ts.map +1 -0
- package/dist/types/ad.types.js +3 -0
- package/dist/types/ad.types.js.map +1 -0
- package/dist/types/adcs.types.d.ts +58 -0
- package/dist/types/adcs.types.d.ts.map +1 -0
- package/dist/types/adcs.types.js +38 -0
- package/dist/types/adcs.types.js.map +1 -0
- package/dist/types/attack-graph.types.d.ts +135 -0
- package/dist/types/attack-graph.types.d.ts.map +1 -0
- package/dist/types/attack-graph.types.js +58 -0
- package/dist/types/attack-graph.types.js.map +1 -0
- package/dist/types/audit.types.d.ts +34 -0
- package/dist/types/audit.types.d.ts.map +1 -0
- package/dist/types/audit.types.js +3 -0
- package/dist/types/audit.types.js.map +1 -0
- package/dist/types/azure.types.d.ts +61 -0
- package/dist/types/azure.types.d.ts.map +1 -0
- package/dist/types/azure.types.js +3 -0
- package/dist/types/azure.types.js.map +1 -0
- package/dist/types/config.types.d.ts +63 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +3 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/error.types.d.ts +33 -0
- package/dist/types/error.types.d.ts.map +1 -0
- package/dist/types/error.types.js +70 -0
- package/dist/types/error.types.js.map +1 -0
- package/dist/types/finding.types.d.ts +133 -0
- package/dist/types/finding.types.d.ts.map +1 -0
- package/dist/types/finding.types.js +3 -0
- package/dist/types/finding.types.js.map +1 -0
- package/dist/types/gpo.types.d.ts +39 -0
- package/dist/types/gpo.types.d.ts.map +1 -0
- package/dist/types/gpo.types.js +15 -0
- package/dist/types/gpo.types.js.map +1 -0
- package/dist/types/token.types.d.ts +26 -0
- package/dist/types/token.types.d.ts.map +1 -0
- package/dist/types/token.types.js +3 -0
- package/dist/types/token.types.js.map +1 -0
- package/dist/types/trust.types.d.ts +45 -0
- package/dist/types/trust.types.d.ts.map +1 -0
- package/dist/types/trust.types.js +71 -0
- package/dist/types/trust.types.js.map +1 -0
- package/dist/utils/entity-converter.d.ts +17 -0
- package/dist/utils/entity-converter.d.ts.map +1 -0
- package/dist/utils/entity-converter.js +285 -0
- package/dist/utils/entity-converter.js.map +1 -0
- package/dist/utils/graph.util.d.ts +66 -0
- package/dist/utils/graph.util.d.ts.map +1 -0
- package/dist/utils/graph.util.js +382 -0
- package/dist/utils/graph.util.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +86 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/type-name-normalizer.d.ts +5 -0
- package/dist/utils/type-name-normalizer.d.ts.map +1 -0
- package/dist/utils/type-name-normalizer.js +218 -0
- package/dist/utils/type-name-normalizer.js.map +1 -0
- package/docker-compose.yml +26 -0
- package/docs/api/README.md +178 -0
- package/docs/api/openapi.yaml +1524 -0
- package/eslint.config.js +54 -0
- package/jest.config.js +38 -0
- package/package.json +97 -0
- package/scripts/fetch-ad-cert.sh +142 -0
- package/src/.gitkeep +0 -0
- package/src/api/.gitkeep +0 -0
- package/src/api/controllers/.gitkeep +0 -0
- package/src/api/controllers/audit.controller.ts +313 -0
- package/src/api/controllers/auth.controller.ts +258 -0
- package/src/api/controllers/export.controller.ts +153 -0
- package/src/api/controllers/health.controller.ts +16 -0
- package/src/api/controllers/jobs.controller.ts +187 -0
- package/src/api/controllers/providers.controller.ts +165 -0
- package/src/api/dto/.gitkeep +0 -0
- package/src/api/dto/AuditRequest.dto.ts +8 -0
- package/src/api/dto/AuditResponse.dto.ts +19 -0
- package/src/api/dto/TokenRequest.dto.ts +8 -0
- package/src/api/dto/TokenResponse.dto.ts +14 -0
- package/src/api/middlewares/.gitkeep +0 -0
- package/src/api/middlewares/authenticate.ts +203 -0
- package/src/api/middlewares/errorHandler.ts +54 -0
- package/src/api/middlewares/rateLimit.ts +35 -0
- package/src/api/middlewares/validate.ts +32 -0
- package/src/api/routes/.gitkeep +0 -0
- package/src/api/routes/audit.routes.ts +77 -0
- package/src/api/routes/auth.routes.ts +71 -0
- package/src/api/routes/export.routes.ts +34 -0
- package/src/api/routes/health.routes.ts +14 -0
- package/src/api/routes/index.ts +40 -0
- package/src/api/routes/providers.routes.ts +24 -0
- package/src/api/validators/.gitkeep +0 -0
- package/src/api/validators/audit.schemas.ts +59 -0
- package/src/api/validators/auth.schemas.ts +59 -0
- package/src/app.ts +87 -0
- package/src/config/.gitkeep +0 -0
- package/src/config/config.schema.ts +108 -0
- package/src/config/index.ts +82 -0
- package/src/container.ts +221 -0
- package/src/data/.gitkeep +0 -0
- package/src/data/database.ts +78 -0
- package/src/data/jobs/token-cleanup.job.ts +166 -0
- package/src/data/migrations/.gitkeep +0 -0
- package/src/data/migrations/001_initial_schema.sql +47 -0
- package/src/data/migrations/migration.runner.ts +125 -0
- package/src/data/models/.gitkeep +0 -0
- package/src/data/models/Token.model.ts +35 -0
- package/src/data/repositories/.gitkeep +0 -0
- package/src/data/repositories/token.repository.ts +160 -0
- package/src/providers/.gitkeep +0 -0
- package/src/providers/azure/.gitkeep +0 -0
- package/src/providers/azure/auth.provider.ts +14 -0
- package/src/providers/azure/azure-errors.ts +189 -0
- package/src/providers/azure/azure-retry.ts +168 -0
- package/src/providers/azure/graph-client.ts +315 -0
- package/src/providers/azure/graph.provider.ts +294 -0
- package/src/providers/azure/queries/app.queries.ts +9 -0
- package/src/providers/azure/queries/policy.queries.ts +9 -0
- package/src/providers/azure/queries/user.queries.ts +10 -0
- package/src/providers/interfaces/.gitkeep +0 -0
- package/src/providers/interfaces/IGraphProvider.ts +117 -0
- package/src/providers/interfaces/ILDAPProvider.ts +142 -0
- package/src/providers/ldap/.gitkeep +0 -0
- package/src/providers/ldap/acl-parser.ts +231 -0
- package/src/providers/ldap/ad-mappers.ts +280 -0
- package/src/providers/ldap/ldap-client.ts +259 -0
- package/src/providers/ldap/ldap-errors.ts +188 -0
- package/src/providers/ldap/ldap-retry.ts +267 -0
- package/src/providers/ldap/ldap-sanitizer.ts +273 -0
- package/src/providers/ldap/ldap.provider.ts +293 -0
- package/src/providers/ldap/queries/computer.queries.ts +9 -0
- package/src/providers/ldap/queries/group.queries.ts +9 -0
- package/src/providers/ldap/queries/user.queries.ts +10 -0
- package/src/providers/smb/smb.provider.ts +653 -0
- package/src/server.ts +60 -0
- package/src/services/.gitkeep +0 -0
- package/src/services/audit/.gitkeep +0 -0
- package/src/services/audit/ad-audit.service.ts +1481 -0
- package/src/services/audit/attack-graph.service.ts +1104 -0
- package/src/services/audit/audit.service.ts +12 -0
- package/src/services/audit/azure-audit.service.ts +286 -0
- package/src/services/audit/detectors/ad/accounts.detector.ts +1232 -0
- package/src/services/audit/detectors/ad/adcs.detector.ts +449 -0
- package/src/services/audit/detectors/ad/advanced.detector.ts +1270 -0
- package/src/services/audit/detectors/ad/attack-paths.detector.ts +600 -0
- package/src/services/audit/detectors/ad/compliance.detector.ts +1421 -0
- package/src/services/audit/detectors/ad/computers.detector.ts +1188 -0
- package/src/services/audit/detectors/ad/gpo.detector.ts +485 -0
- package/src/services/audit/detectors/ad/groups.detector.ts +685 -0
- package/src/services/audit/detectors/ad/index.ts +84 -0
- package/src/services/audit/detectors/ad/kerberos.detector.ts +424 -0
- package/src/services/audit/detectors/ad/monitoring.detector.ts +501 -0
- package/src/services/audit/detectors/ad/network.detector.ts +538 -0
- package/src/services/audit/detectors/ad/password.detector.ts +324 -0
- package/src/services/audit/detectors/ad/permissions.detector.ts +637 -0
- package/src/services/audit/detectors/ad/trusts.detector.ts +315 -0
- package/src/services/audit/detectors/azure/app-security.detector.ts +246 -0
- package/src/services/audit/detectors/azure/conditional-access.detector.ts +186 -0
- package/src/services/audit/detectors/azure/privilege-security.detector.ts +176 -0
- package/src/services/audit/detectors/azure/user-security.detector.ts +280 -0
- package/src/services/audit/detectors/index.ts +18 -0
- package/src/services/audit/response-formatter.ts +604 -0
- package/src/services/audit/scoring.service.ts +234 -0
- package/src/services/auth/.gitkeep +0 -0
- package/src/services/auth/crypto.service.ts +230 -0
- package/src/services/auth/errors.ts +47 -0
- package/src/services/auth/token.service.ts +420 -0
- package/src/services/config/.gitkeep +0 -0
- package/src/services/config/config.service.ts +75 -0
- package/src/services/export/.gitkeep +0 -0
- package/src/services/export/export.service.ts +99 -0
- package/src/services/export/formatters/csv.formatter.ts +124 -0
- package/src/services/export/formatters/json.formatter.ts +160 -0
- package/src/services/jobs/azure-job-runner.ts +312 -0
- package/src/services/jobs/index.ts +9 -0
- package/src/services/jobs/job-runner.ts +1280 -0
- package/src/services/jobs/job-store.ts +384 -0
- package/src/services/jobs/job.types.ts +182 -0
- package/src/types/.gitkeep +0 -0
- package/src/types/ad.types.ts +91 -0
- package/src/types/adcs.types.ts +107 -0
- package/src/types/attack-graph.types.ts +260 -0
- package/src/types/audit.types.ts +42 -0
- package/src/types/azure.types.ts +68 -0
- package/src/types/config.types.ts +79 -0
- package/src/types/error.types.ts +69 -0
- package/src/types/finding.types.ts +284 -0
- package/src/types/gpo.types.ts +72 -0
- package/src/types/smb2.d.ts +73 -0
- package/src/types/token.types.ts +32 -0
- package/src/types/trust.types.ts +140 -0
- package/src/utils/.gitkeep +0 -0
- package/src/utils/entity-converter.ts +453 -0
- package/src/utils/graph.util.ts +609 -0
- package/src/utils/logger.ts +111 -0
- package/src/utils/type-name-normalizer.ts +302 -0
- package/tests/.gitkeep +0 -0
- package/tests/e2e/.gitkeep +0 -0
- package/tests/fixtures/.gitkeep +0 -0
- package/tests/integration/.gitkeep +0 -0
- package/tests/integration/README.md +156 -0
- package/tests/integration/ad-audit.integration.test.ts +216 -0
- package/tests/integration/api/.gitkeep +0 -0
- package/tests/integration/api/endpoints.integration.test.ts +431 -0
- package/tests/integration/auth/jwt-authentication.integration.test.ts +358 -0
- package/tests/integration/providers/.gitkeep +0 -0
- package/tests/integration/providers/azure-basic.integration.test.ts +167 -0
- package/tests/integration/providers/ldap-basic.integration.test.ts +152 -0
- package/tests/integration/providers/ldap-connectivity.test.ts +44 -0
- package/tests/integration/providers/ldap-provider.integration.test.ts +347 -0
- package/tests/mocks/.gitkeep +0 -0
- package/tests/setup.ts +16 -0
- package/tests/unit/.gitkeep +0 -0
- package/tests/unit/api/middlewares/authenticate.test.ts +446 -0
- package/tests/unit/providers/.gitkeep +0 -0
- package/tests/unit/providers/azure/azure-errors.test.ts +193 -0
- package/tests/unit/providers/azure/azure-retry.test.ts +254 -0
- package/tests/unit/providers/azure/graph-provider.test.ts +313 -0
- package/tests/unit/providers/ldap/ad-mappers.test.ts +392 -0
- package/tests/unit/providers/ldap/ldap-provider.test.ts +376 -0
- package/tests/unit/providers/ldap/ldap-retry.test.ts +377 -0
- package/tests/unit/providers/ldap/ldap-sanitizer.test.ts +301 -0
- package/tests/unit/sample.test.ts +19 -0
- package/tests/unit/services/.gitkeep +0 -0
- package/tests/unit/services/audit/detectors/ad/accounts.detector.test.ts +393 -0
- package/tests/unit/services/audit/detectors/ad/advanced.detector.test.ts +380 -0
- package/tests/unit/services/audit/detectors/ad/computers.detector.test.ts +440 -0
- package/tests/unit/services/audit/detectors/ad/groups.detector.test.ts +276 -0
- package/tests/unit/services/audit/detectors/ad/kerberos.detector.test.ts +215 -0
- package/tests/unit/services/audit/detectors/ad/password.detector.test.ts +226 -0
- package/tests/unit/services/audit/detectors/ad/permissions.detector.test.ts +244 -0
- package/tests/unit/services/audit/detectors/azure/app-security.detector.test.ts +349 -0
- package/tests/unit/services/audit/detectors/azure/conditional-access.detector.test.ts +374 -0
- package/tests/unit/services/audit/detectors/azure/privilege-security.detector.test.ts +374 -0
- package/tests/unit/services/audit/detectors/azure/user-security.detector.test.ts +297 -0
- package/tests/unit/services/auth/crypto.service.test.ts +296 -0
- package/tests/unit/services/auth/token.service.test.ts +579 -0
- package/tests/unit/services/export/export.service.test.ts +241 -0
- package/tests/unit/services/export/formatters/csv.formatter.test.ts +270 -0
- package/tests/unit/services/export/formatters/json.formatter.test.ts +258 -0
- package/tests/unit/utils/.gitkeep +0 -0
- package/tsconfig.json +50 -0
|
@@ -0,0 +1,867 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectShadowCredentials = detectShadowCredentials;
|
|
4
|
+
exports.detectRbcdAbuse = detectRbcdAbuse;
|
|
5
|
+
exports.detectEsc1VulnerableTemplate = detectEsc1VulnerableTemplate;
|
|
6
|
+
exports.detectEsc2AnyPurpose = detectEsc2AnyPurpose;
|
|
7
|
+
exports.detectEsc3EnrollmentAgent = detectEsc3EnrollmentAgent;
|
|
8
|
+
exports.detectEsc4VulnerableTemplateAcl = detectEsc4VulnerableTemplateAcl;
|
|
9
|
+
exports.detectEsc6EditfAttributeSubjectAltName2 = detectEsc6EditfAttributeSubjectAltName2;
|
|
10
|
+
exports.detectLapsPasswordReadable = detectLapsPasswordReadable;
|
|
11
|
+
exports.detectReplicationRights = detectReplicationRights;
|
|
12
|
+
exports.detectDcsyncCapable = detectDcsyncCapable;
|
|
13
|
+
exports.detectEsc8HttpEnrollment = detectEsc8HttpEnrollment;
|
|
14
|
+
exports.detectLapsNotDeployed = detectLapsNotDeployed;
|
|
15
|
+
exports.detectLapsLegacyAttribute = detectLapsLegacyAttribute;
|
|
16
|
+
exports.detectDuplicateSpn = detectDuplicateSpn;
|
|
17
|
+
exports.detectWeakPasswordPolicy = detectWeakPasswordPolicy;
|
|
18
|
+
exports.detectWeakKerberosPolicy = detectWeakKerberosPolicy;
|
|
19
|
+
exports.detectMachineAccountQuotaAbuse = detectMachineAccountQuotaAbuse;
|
|
20
|
+
exports.detectMachineAccountQuotaHigh = detectMachineAccountQuotaHigh;
|
|
21
|
+
exports.detectDelegationPrivilege = detectDelegationPrivilege;
|
|
22
|
+
exports.detectForeignSecurityPrincipals = detectForeignSecurityPrincipals;
|
|
23
|
+
exports.detectNtlmRelayOpportunity = detectNtlmRelayOpportunity;
|
|
24
|
+
exports.detectLapsPasswordSet = detectLapsPasswordSet;
|
|
25
|
+
exports.detectLapsPasswordLeaked = detectLapsPasswordLeaked;
|
|
26
|
+
exports.detectAdcsWeakPermissions = detectAdcsWeakPermissions;
|
|
27
|
+
exports.detectDangerousLogonScripts = detectDangerousLogonScripts;
|
|
28
|
+
exports.detectAnonymousLdapAccess = detectAnonymousLdapAccess;
|
|
29
|
+
exports.detectRecycleBinDisabled = detectRecycleBinDisabled;
|
|
30
|
+
exports.detectLdapSigningDisabled = detectLdapSigningDisabled;
|
|
31
|
+
exports.detectLdapChannelBindingDisabled = detectLdapChannelBindingDisabled;
|
|
32
|
+
exports.detectSmbV1Enabled = detectSmbV1Enabled;
|
|
33
|
+
exports.detectSmbSigningDisabled = detectSmbSigningDisabled;
|
|
34
|
+
exports.detectAuditPolicyWeak = detectAuditPolicyWeak;
|
|
35
|
+
exports.detectPowershellLoggingDisabled = detectPowershellLoggingDisabled;
|
|
36
|
+
exports.detectDsHeuristicsModified = detectDsHeuristicsModified;
|
|
37
|
+
exports.detectAdminSdHolderModified = detectAdminSdHolderModified;
|
|
38
|
+
exports.detectExchangePrivEscPath = detectExchangePrivEscPath;
|
|
39
|
+
exports.detectAdvancedVulnerabilities = detectAdvancedVulnerabilities;
|
|
40
|
+
const entity_converter_1 = require("../../../../utils/entity-converter");
|
|
41
|
+
function detectShadowCredentials(users, includeDetails) {
|
|
42
|
+
const affected = users.filter((u) => {
|
|
43
|
+
const keyLink = u['msDS-KeyCredentialLink'];
|
|
44
|
+
return keyLink && (Array.isArray(keyLink) ? keyLink.length > 0 : keyLink !== '');
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
type: 'SHADOW_CREDENTIALS',
|
|
48
|
+
severity: 'critical',
|
|
49
|
+
category: 'advanced',
|
|
50
|
+
title: 'Shadow Credentials',
|
|
51
|
+
description: 'msDS-KeyCredentialLink attribute configured. Allows Kerberos authentication bypass by adding arbitrary public keys.',
|
|
52
|
+
count: affected.length,
|
|
53
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function detectRbcdAbuse(users, includeDetails) {
|
|
57
|
+
const affected = users.filter((u) => {
|
|
58
|
+
const rbcdAttr = u['msDS-AllowedToActOnBehalfOfOtherIdentity'];
|
|
59
|
+
return rbcdAttr && (Array.isArray(rbcdAttr) ? rbcdAttr.length > 0 : rbcdAttr !== '');
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
type: 'RBCD_ABUSE',
|
|
63
|
+
severity: 'critical',
|
|
64
|
+
category: 'advanced',
|
|
65
|
+
title: 'RBCD Abuse',
|
|
66
|
+
description: 'msDS-AllowedToActOnBehalfOfOtherIdentity configured. Enables privilege escalation via resource-based delegation.',
|
|
67
|
+
count: affected.length,
|
|
68
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function detectEsc1VulnerableTemplate(templates, includeDetails) {
|
|
72
|
+
const affected = templates.filter((t) => {
|
|
73
|
+
const hasClientAuth = t.pKIExtendedKeyUsage?.includes('1.3.6.1.5.5.7.3.2');
|
|
74
|
+
const enrolleeSuppliesSubject = t['msPKI-Certificate-Name-Flag'] && (t['msPKI-Certificate-Name-Flag'] & 0x1) !== 0;
|
|
75
|
+
return hasClientAuth && enrolleeSuppliesSubject;
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
type: 'ESC1_VULNERABLE_TEMPLATE',
|
|
79
|
+
severity: 'high',
|
|
80
|
+
category: 'advanced',
|
|
81
|
+
title: 'ESC1 Vulnerable Template',
|
|
82
|
+
description: 'ADCS template with client auth + enrollee supplies subject. Enables domain compromise by obtaining cert for any user.',
|
|
83
|
+
count: affected.length,
|
|
84
|
+
affectedEntities: includeDetails ? affected.map((t) => t.dn) : undefined,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function detectEsc2AnyPurpose(templates, includeDetails) {
|
|
88
|
+
const affected = templates.filter((t) => {
|
|
89
|
+
const hasAnyPurpose = t.pKIExtendedKeyUsage?.includes('2.5.29.37.0');
|
|
90
|
+
const isEmpty = !t.pKIExtendedKeyUsage || t.pKIExtendedKeyUsage.length === 0;
|
|
91
|
+
return hasAnyPurpose || isEmpty;
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
type: 'ESC2_ANY_PURPOSE',
|
|
95
|
+
severity: 'high',
|
|
96
|
+
category: 'advanced',
|
|
97
|
+
title: 'ESC2 Any Purpose',
|
|
98
|
+
description: 'ADCS template with Any Purpose EKU or no usage restriction. Certificate can be used for domain authentication.',
|
|
99
|
+
count: affected.length,
|
|
100
|
+
affectedEntities: includeDetails ? affected.map((t) => t.dn) : undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function detectEsc3EnrollmentAgent(templates, includeDetails) {
|
|
104
|
+
const affected = templates.filter((t) => {
|
|
105
|
+
return t.pKIExtendedKeyUsage?.includes('1.3.6.1.4.1.311.20.2.1');
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
type: 'ESC3_ENROLLMENT_AGENT',
|
|
109
|
+
severity: 'high',
|
|
110
|
+
category: 'advanced',
|
|
111
|
+
title: 'ESC3 Enrollment Agent',
|
|
112
|
+
description: 'ADCS template with enrollment agent EKU. Can request certificates on behalf of other users.',
|
|
113
|
+
count: affected.length,
|
|
114
|
+
affectedEntities: includeDetails ? affected.map((t) => t.dn) : undefined,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function detectEsc4VulnerableTemplateAcl(templates, includeDetails) {
|
|
118
|
+
const affected = templates.filter((t) => {
|
|
119
|
+
return t.hasWeakAcl;
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
type: 'ESC4_VULNERABLE_TEMPLATE_ACL',
|
|
123
|
+
severity: 'high',
|
|
124
|
+
category: 'advanced',
|
|
125
|
+
title: 'ESC4 Vulnerable Template ACL',
|
|
126
|
+
description: 'Certificate template with weak ACLs. Can modify template to make it vulnerable to ESC1/ESC2.',
|
|
127
|
+
count: affected.length,
|
|
128
|
+
affectedEntities: includeDetails ? affected.map((t) => t.dn) : undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function detectEsc6EditfAttributeSubjectAltName2(cas, includeDetails) {
|
|
132
|
+
const affected = cas.filter((ca) => {
|
|
133
|
+
return ca.flags && (ca.flags & 0x40000) !== 0;
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
type: 'ESC6_EDITF_ATTRIBUTESUBJECTALTNAME2',
|
|
137
|
+
severity: 'high',
|
|
138
|
+
category: 'advanced',
|
|
139
|
+
title: 'ESC6 EDITF Flag',
|
|
140
|
+
description: 'ADCS CA with EDITF_ATTRIBUTESUBJECTALTNAME2 flag. Allows specifying arbitrary SAN in certificate requests.',
|
|
141
|
+
count: affected.length,
|
|
142
|
+
affectedEntities: includeDetails ? affected.map((ca) => ca.dn) : undefined,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function detectLapsPasswordReadable(computers, includeDetails) {
|
|
146
|
+
const affected = computers.filter((c) => {
|
|
147
|
+
return c.lapsPasswordReadableByNonAdmins;
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
type: 'LAPS_PASSWORD_READABLE',
|
|
151
|
+
severity: 'high',
|
|
152
|
+
category: 'advanced',
|
|
153
|
+
title: 'LAPS Password Readable',
|
|
154
|
+
description: 'Non-admin users can read LAPS password attributes. Exposure of local admin passwords.',
|
|
155
|
+
count: affected.length,
|
|
156
|
+
affectedEntities: includeDetails ? affected.map((c) => c.dn) : undefined,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function detectReplicationRights(users, includeDetails) {
|
|
160
|
+
const affected = users.filter((u) => {
|
|
161
|
+
if (u.adminCount !== 1)
|
|
162
|
+
return false;
|
|
163
|
+
if (!u.memberOf)
|
|
164
|
+
return true;
|
|
165
|
+
const isInStandardAdminGroups = u.memberOf.some((dn) => {
|
|
166
|
+
return (dn.includes('CN=Domain Admins') ||
|
|
167
|
+
dn.includes('CN=Enterprise Admins') ||
|
|
168
|
+
dn.includes('CN=Administrators'));
|
|
169
|
+
});
|
|
170
|
+
return !isInStandardAdminGroups;
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
type: 'REPLICATION_RIGHTS',
|
|
174
|
+
severity: 'high',
|
|
175
|
+
category: 'advanced',
|
|
176
|
+
title: 'Replication Rights',
|
|
177
|
+
description: 'Account with adminCount=1 outside standard admin groups. May have replication rights (DCSync).',
|
|
178
|
+
count: affected.length,
|
|
179
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function detectDcsyncCapable(users, includeDetails) {
|
|
183
|
+
const affected = users.filter((u) => {
|
|
184
|
+
return u.hasDcsyncRights;
|
|
185
|
+
});
|
|
186
|
+
return {
|
|
187
|
+
type: 'DCSYNC_CAPABLE',
|
|
188
|
+
severity: 'high',
|
|
189
|
+
category: 'advanced',
|
|
190
|
+
title: 'DCSync Capable',
|
|
191
|
+
description: 'Account with DS-Replication-Get-Changes and DS-Replication-Get-Changes-All rights. Can extract all password hashes.',
|
|
192
|
+
count: affected.length,
|
|
193
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function detectEsc8HttpEnrollment(cas, includeDetails) {
|
|
197
|
+
const affected = cas.filter((ca) => {
|
|
198
|
+
return ca.webEnrollment && ca.webEnrollment.protocol === 'http';
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
type: 'ESC8_HTTP_ENROLLMENT',
|
|
202
|
+
severity: 'medium',
|
|
203
|
+
category: 'advanced',
|
|
204
|
+
title: 'ESC8 HTTP Enrollment',
|
|
205
|
+
description: 'ADCS web enrollment via HTTP. Enables NTLM relay attacks against certificate enrollment.',
|
|
206
|
+
count: affected.length,
|
|
207
|
+
affectedEntities: includeDetails ? affected.map((ca) => ca.dn) : undefined,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function detectLapsNotDeployed(computers, includeDetails) {
|
|
211
|
+
const affected = computers.filter((c) => {
|
|
212
|
+
return !('ms-Mcs-AdmPwd' in c) && !('msLAPS-Password' in c);
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
type: 'LAPS_NOT_DEPLOYED',
|
|
216
|
+
severity: 'medium',
|
|
217
|
+
category: 'advanced',
|
|
218
|
+
title: 'LAPS Not Deployed',
|
|
219
|
+
description: 'LAPS not deployed on domain computers. Shared/static local admin passwords across workstations.',
|
|
220
|
+
count: affected.length,
|
|
221
|
+
affectedEntities: includeDetails ? affected.map((c) => c.dn) : undefined,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function detectLapsLegacyAttribute(computers, includeDetails) {
|
|
225
|
+
const affected = computers.filter((c) => {
|
|
226
|
+
return 'ms-Mcs-AdmPwd' in c && !('msLAPS-Password' in c);
|
|
227
|
+
});
|
|
228
|
+
return {
|
|
229
|
+
type: 'LAPS_LEGACY_ATTRIBUTE',
|
|
230
|
+
severity: 'medium',
|
|
231
|
+
category: 'advanced',
|
|
232
|
+
title: 'LAPS Legacy Attribute',
|
|
233
|
+
description: 'Legacy LAPS attribute used instead of Windows LAPS. Less secure implementation.',
|
|
234
|
+
count: affected.length,
|
|
235
|
+
affectedEntities: includeDetails ? affected.map((c) => c.dn) : undefined,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function detectDuplicateSpn(users, includeDetails) {
|
|
239
|
+
const spnMap = new Map();
|
|
240
|
+
users.forEach((u) => {
|
|
241
|
+
const spns = u.servicePrincipalName;
|
|
242
|
+
if (spns && Array.isArray(spns)) {
|
|
243
|
+
spns.forEach((spn) => {
|
|
244
|
+
if (!spnMap.has(spn)) {
|
|
245
|
+
spnMap.set(spn, []);
|
|
246
|
+
}
|
|
247
|
+
spnMap.get(spn).push(u.dn);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
const affected = [];
|
|
252
|
+
spnMap.forEach((dns, _spn) => {
|
|
253
|
+
if (dns.length > 1) {
|
|
254
|
+
affected.push(...dns);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
return {
|
|
258
|
+
type: 'DUPLICATE_SPN',
|
|
259
|
+
severity: 'medium',
|
|
260
|
+
category: 'advanced',
|
|
261
|
+
title: 'Duplicate SPN',
|
|
262
|
+
description: 'Service Principal Name registered multiple times. Can cause Kerberos authentication failures.',
|
|
263
|
+
count: affected.length,
|
|
264
|
+
affectedEntities: includeDetails ? affected : undefined,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function detectWeakPasswordPolicy(domain, includeDetails) {
|
|
268
|
+
if (!domain) {
|
|
269
|
+
return {
|
|
270
|
+
type: 'WEAK_PASSWORD_POLICY',
|
|
271
|
+
severity: 'medium',
|
|
272
|
+
category: 'advanced',
|
|
273
|
+
title: 'Weak Password Policy',
|
|
274
|
+
description: 'Unable to check domain password policy.',
|
|
275
|
+
count: 0,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const minPwdLength = domain.minPwdLength || 0;
|
|
279
|
+
const maxPwdAge = domain.maxPwdAge || 0;
|
|
280
|
+
const pwdHistoryLength = domain.pwdHistoryLength || 0;
|
|
281
|
+
const isWeak = minPwdLength < 14 || maxPwdAge > 90 || pwdHistoryLength < 24;
|
|
282
|
+
return {
|
|
283
|
+
type: 'WEAK_PASSWORD_POLICY',
|
|
284
|
+
severity: 'medium',
|
|
285
|
+
category: 'advanced',
|
|
286
|
+
title: 'Weak Password Policy',
|
|
287
|
+
description: 'Domain password policy below minimum standards. Enables easier password cracking.',
|
|
288
|
+
count: isWeak ? 1 : 0,
|
|
289
|
+
affectedEntities: includeDetails && isWeak ? [domain.dn] : undefined,
|
|
290
|
+
details: isWeak
|
|
291
|
+
? {
|
|
292
|
+
minPwdLength,
|
|
293
|
+
maxPwdAge,
|
|
294
|
+
pwdHistoryLength,
|
|
295
|
+
}
|
|
296
|
+
: undefined,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function detectWeakKerberosPolicy(domain, includeDetails) {
|
|
300
|
+
if (!domain) {
|
|
301
|
+
return {
|
|
302
|
+
type: 'WEAK_KERBEROS_POLICY',
|
|
303
|
+
severity: 'medium',
|
|
304
|
+
category: 'advanced',
|
|
305
|
+
title: 'Weak Kerberos Policy',
|
|
306
|
+
description: 'Unable to check Kerberos policy.',
|
|
307
|
+
count: 0,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
const maxTicketAge = domain.maxTicketAge || 0;
|
|
311
|
+
const maxRenewAge = domain.maxRenewAge || 0;
|
|
312
|
+
const isWeak = maxTicketAge > 10 || maxRenewAge > 7;
|
|
313
|
+
return {
|
|
314
|
+
type: 'WEAK_KERBEROS_POLICY',
|
|
315
|
+
severity: 'medium',
|
|
316
|
+
category: 'advanced',
|
|
317
|
+
title: 'Weak Kerberos Policy',
|
|
318
|
+
description: 'Kerberos ticket lifetimes exceed recommended values. Longer window for ticket-based attacks.',
|
|
319
|
+
count: isWeak ? 1 : 0,
|
|
320
|
+
affectedEntities: includeDetails && isWeak ? [domain.dn] : undefined,
|
|
321
|
+
details: isWeak
|
|
322
|
+
? {
|
|
323
|
+
maxTicketAge,
|
|
324
|
+
maxRenewAge,
|
|
325
|
+
}
|
|
326
|
+
: undefined,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function detectMachineAccountQuotaAbuse(domain, includeDetails) {
|
|
330
|
+
if (!domain) {
|
|
331
|
+
return {
|
|
332
|
+
type: 'MACHINE_ACCOUNT_QUOTA_ABUSE',
|
|
333
|
+
severity: 'medium',
|
|
334
|
+
category: 'advanced',
|
|
335
|
+
title: 'Machine Account Quota Abuse',
|
|
336
|
+
description: 'Unable to check machine account quota.',
|
|
337
|
+
count: 0,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
const quota = domain['ms-DS-MachineAccountQuota'];
|
|
341
|
+
const isVulnerable = typeof quota === 'number' && quota > 0;
|
|
342
|
+
return {
|
|
343
|
+
type: 'MACHINE_ACCOUNT_QUOTA_ABUSE',
|
|
344
|
+
severity: 'medium',
|
|
345
|
+
category: 'advanced',
|
|
346
|
+
title: 'Machine Account Quota Abuse',
|
|
347
|
+
description: 'ms-DS-MachineAccountQuota > 0. Non-admin users can join computers to domain (potential Kerberos attacks).',
|
|
348
|
+
count: isVulnerable ? 1 : 0,
|
|
349
|
+
affectedEntities: includeDetails && isVulnerable ? [domain.dn] : undefined,
|
|
350
|
+
details: isVulnerable
|
|
351
|
+
? {
|
|
352
|
+
quota,
|
|
353
|
+
}
|
|
354
|
+
: undefined,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function detectMachineAccountQuotaHigh(domain, includeDetails) {
|
|
358
|
+
if (!domain) {
|
|
359
|
+
return {
|
|
360
|
+
type: 'MACHINE_ACCOUNT_QUOTA_HIGH',
|
|
361
|
+
severity: 'high',
|
|
362
|
+
category: 'advanced',
|
|
363
|
+
title: 'Machine Account Quota Elevated',
|
|
364
|
+
description: 'Unable to check machine account quota.',
|
|
365
|
+
count: 0,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
const quota = domain['ms-DS-MachineAccountQuota'];
|
|
369
|
+
const DEFAULT_QUOTA = 10;
|
|
370
|
+
const isElevated = typeof quota === 'number' && quota > DEFAULT_QUOTA;
|
|
371
|
+
return {
|
|
372
|
+
type: 'MACHINE_ACCOUNT_QUOTA_HIGH',
|
|
373
|
+
severity: 'high',
|
|
374
|
+
category: 'advanced',
|
|
375
|
+
title: 'Machine Account Quota Elevated Above Default',
|
|
376
|
+
description: 'ms-DS-MachineAccountQuota is higher than the default (10). Someone intentionally increased this value, allowing non-admin users to join more computers to the domain.',
|
|
377
|
+
count: isElevated ? 1 : 0,
|
|
378
|
+
affectedEntities: includeDetails && isElevated ? [domain.dn] : undefined,
|
|
379
|
+
details: isElevated
|
|
380
|
+
? {
|
|
381
|
+
currentQuota: quota,
|
|
382
|
+
defaultQuota: DEFAULT_QUOTA,
|
|
383
|
+
recommendation: 'Set ms-DS-MachineAccountQuota to 0 to prevent non-admin domain joins.',
|
|
384
|
+
}
|
|
385
|
+
: undefined,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function detectDelegationPrivilege(users, includeDetails) {
|
|
389
|
+
const affected = users.filter((u) => {
|
|
390
|
+
return u.hasSeEnableDelegationPrivilege;
|
|
391
|
+
});
|
|
392
|
+
return {
|
|
393
|
+
type: 'DELEGATION_PRIVILEGE',
|
|
394
|
+
severity: 'medium',
|
|
395
|
+
category: 'advanced',
|
|
396
|
+
title: 'Delegation Privilege',
|
|
397
|
+
description: 'Account has SeEnableDelegationPrivilege. Can enable delegation on user/computer accounts.',
|
|
398
|
+
count: affected.length,
|
|
399
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function detectForeignSecurityPrincipals(fsps, includeDetails) {
|
|
403
|
+
return {
|
|
404
|
+
type: 'FOREIGN_SECURITY_PRINCIPALS',
|
|
405
|
+
severity: 'medium',
|
|
406
|
+
category: 'advanced',
|
|
407
|
+
title: 'Foreign Security Principals',
|
|
408
|
+
description: 'Foreign security principals from external forests. Potential for cross-forest privilege escalation.',
|
|
409
|
+
count: fsps.length,
|
|
410
|
+
affectedEntities: includeDetails ? fsps.map((fsp) => fsp.dn) : undefined,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function detectNtlmRelayOpportunity(domain, includeDetails) {
|
|
414
|
+
if (!domain) {
|
|
415
|
+
return {
|
|
416
|
+
type: 'NTLM_RELAY_OPPORTUNITY',
|
|
417
|
+
severity: 'medium',
|
|
418
|
+
category: 'advanced',
|
|
419
|
+
title: 'NTLM Relay Opportunity',
|
|
420
|
+
description: 'Unable to check LDAP signing configuration.',
|
|
421
|
+
count: 0,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
const ldapSigningRequired = domain.ldapSigningRequired;
|
|
425
|
+
const channelBindingRequired = domain.channelBindingRequired;
|
|
426
|
+
const isVulnerable = !ldapSigningRequired || !channelBindingRequired;
|
|
427
|
+
return {
|
|
428
|
+
type: 'NTLM_RELAY_OPPORTUNITY',
|
|
429
|
+
severity: 'medium',
|
|
430
|
+
category: 'advanced',
|
|
431
|
+
title: 'NTLM Relay Opportunity',
|
|
432
|
+
description: 'LDAP signing or channel binding not enforced. Enables NTLM relay attacks.',
|
|
433
|
+
count: isVulnerable ? 1 : 0,
|
|
434
|
+
affectedEntities: includeDetails && isVulnerable ? [domain.dn] : undefined,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function detectLapsPasswordSet(computers, includeDetails) {
|
|
438
|
+
const affected = computers.filter((c) => {
|
|
439
|
+
return 'ms-Mcs-AdmPwd' in c || 'msLAPS-Password' in c;
|
|
440
|
+
});
|
|
441
|
+
return {
|
|
442
|
+
type: 'LAPS_PASSWORD_SET',
|
|
443
|
+
severity: 'low',
|
|
444
|
+
category: 'advanced',
|
|
445
|
+
title: 'LAPS Password Set',
|
|
446
|
+
description: 'LAPS password successfully managed. Informational - indicates proper LAPS deployment.',
|
|
447
|
+
count: affected.length,
|
|
448
|
+
affectedEntities: includeDetails ? affected.map((c) => c.dn) : undefined,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function detectLapsPasswordLeaked(computers, includeDetails) {
|
|
452
|
+
const affected = computers.filter((c) => {
|
|
453
|
+
return c.lapsPasswordExcessiveReaders;
|
|
454
|
+
});
|
|
455
|
+
return {
|
|
456
|
+
type: 'LAPS_PASSWORD_LEAKED',
|
|
457
|
+
severity: 'low',
|
|
458
|
+
category: 'advanced',
|
|
459
|
+
title: 'LAPS Password Leaked',
|
|
460
|
+
description: 'LAPS password visible to too many users. Reduces effectiveness of LAPS.',
|
|
461
|
+
count: affected.length,
|
|
462
|
+
affectedEntities: includeDetails ? affected.map((c) => c.dn) : undefined,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function detectAdcsWeakPermissions(templates, includeDetails) {
|
|
466
|
+
const affected = templates.filter((t) => {
|
|
467
|
+
return t.hasWeakEnrollmentAcl || t.hasGenericAllPermission;
|
|
468
|
+
});
|
|
469
|
+
return {
|
|
470
|
+
type: 'ADCS_WEAK_PERMISSIONS',
|
|
471
|
+
severity: 'medium',
|
|
472
|
+
category: 'advanced',
|
|
473
|
+
title: 'ADCS Weak Permissions',
|
|
474
|
+
description: 'Weak permissions on ADCS objects or certificate templates allow unauthorized enrollment.',
|
|
475
|
+
count: affected.length,
|
|
476
|
+
affectedEntities: includeDetails ? affected.map((t) => t.dn || t.name) : undefined,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function detectDangerousLogonScripts(users, includeDetails) {
|
|
480
|
+
const affected = users.filter((u) => {
|
|
481
|
+
const scriptPath = u.scriptPath;
|
|
482
|
+
return scriptPath && (scriptPath.includes('\\\\') || scriptPath.startsWith('//'));
|
|
483
|
+
});
|
|
484
|
+
return {
|
|
485
|
+
type: 'DANGEROUS_LOGON_SCRIPTS',
|
|
486
|
+
severity: 'medium',
|
|
487
|
+
category: 'advanced',
|
|
488
|
+
title: 'Dangerous Logon Scripts',
|
|
489
|
+
description: 'Logon scripts with weak ACLs can be modified by attackers for code execution on user login.',
|
|
490
|
+
count: affected.length,
|
|
491
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function detectAnonymousLdapAccess(anonymousAccessAllowed, domain, includeDetails) {
|
|
495
|
+
return {
|
|
496
|
+
type: 'ANONYMOUS_LDAP_ACCESS',
|
|
497
|
+
severity: 'medium',
|
|
498
|
+
category: 'advanced',
|
|
499
|
+
title: 'Anonymous LDAP Access Allowed',
|
|
500
|
+
description: 'LDAP server accepts anonymous binds. Attackers can enumerate AD objects (users, groups, computers) without valid credentials.',
|
|
501
|
+
count: anonymousAccessAllowed ? 1 : 0,
|
|
502
|
+
affectedEntities: includeDetails && anonymousAccessAllowed && domain ? [domain.dn] : undefined,
|
|
503
|
+
details: anonymousAccessAllowed
|
|
504
|
+
? {
|
|
505
|
+
recommendation: 'Configure "Network security: LDAP client signing requirements" and restrict anonymous access via dsHeuristics.',
|
|
506
|
+
currentStatus: 'Anonymous bind allowed',
|
|
507
|
+
}
|
|
508
|
+
: undefined,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function detectRecycleBinDisabled(domain, includeDetails) {
|
|
512
|
+
if (!domain) {
|
|
513
|
+
return {
|
|
514
|
+
type: 'RECYCLE_BIN_DISABLED',
|
|
515
|
+
severity: 'medium',
|
|
516
|
+
category: 'advanced',
|
|
517
|
+
title: 'AD Recycle Bin Status Unknown',
|
|
518
|
+
description: 'Unable to determine AD Recycle Bin status.',
|
|
519
|
+
count: 0,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
const recycleBinEnabled = domain.recycleBinEnabled === true;
|
|
523
|
+
return {
|
|
524
|
+
type: 'RECYCLE_BIN_DISABLED',
|
|
525
|
+
severity: 'medium',
|
|
526
|
+
category: 'advanced',
|
|
527
|
+
title: 'AD Recycle Bin Not Enabled',
|
|
528
|
+
description: 'Active Directory Recycle Bin is not enabled. Deleted objects cannot be easily recovered, which complicates incident response and may lead to permanent data loss.',
|
|
529
|
+
count: recycleBinEnabled ? 0 : 1,
|
|
530
|
+
affectedEntities: includeDetails && !recycleBinEnabled ? [domain.dn] : undefined,
|
|
531
|
+
details: !recycleBinEnabled
|
|
532
|
+
? {
|
|
533
|
+
recommendation: 'Enable AD Recycle Bin feature. Note: This requires forest functional level 2008 R2 or higher and is irreversible.',
|
|
534
|
+
currentStatus: 'Disabled',
|
|
535
|
+
}
|
|
536
|
+
: undefined,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
function detectLdapSigningDisabled(gpoSettings, domain, includeDetails) {
|
|
540
|
+
if (gpoSettings && gpoSettings.ldapServerIntegrity !== undefined) {
|
|
541
|
+
const signingDisabled = gpoSettings.ldapServerIntegrity === 0;
|
|
542
|
+
return {
|
|
543
|
+
type: 'LDAP_SIGNING_DISABLED',
|
|
544
|
+
severity: 'critical',
|
|
545
|
+
category: 'advanced',
|
|
546
|
+
title: 'LDAP Signing Not Required',
|
|
547
|
+
description: 'LDAP server signing is not required. This allows NTLM relay attacks and man-in-the-middle attacks against LDAP connections.',
|
|
548
|
+
count: signingDisabled ? 1 : 0,
|
|
549
|
+
affectedEntities: includeDetails && signingDisabled && domain ? [domain.dn] : undefined,
|
|
550
|
+
details: signingDisabled
|
|
551
|
+
? {
|
|
552
|
+
recommendation: 'Configure "Domain controller: LDAP server signing requirements" to "Require signing".',
|
|
553
|
+
currentSetting: gpoSettings.ldapServerIntegrity,
|
|
554
|
+
requiredSetting: 2,
|
|
555
|
+
}
|
|
556
|
+
: undefined,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
type: 'LDAP_SIGNING_DISABLED',
|
|
561
|
+
severity: 'critical',
|
|
562
|
+
category: 'advanced',
|
|
563
|
+
title: 'LDAP Signing Not Configured in GPO',
|
|
564
|
+
description: 'LDAP signing is not configured via Group Policy. Windows defaults do not require LDAP signing, making this environment vulnerable to LDAP relay attacks.',
|
|
565
|
+
count: 1,
|
|
566
|
+
affectedEntities: includeDetails && domain ? [domain.dn] : undefined,
|
|
567
|
+
details: {
|
|
568
|
+
recommendation: 'Configure "Domain controller: LDAP server signing requirements" to "Require signing" via Group Policy.',
|
|
569
|
+
note: 'No GPO security template found. Windows defaults do not require LDAP signing.',
|
|
570
|
+
},
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
function detectLdapChannelBindingDisabled(gpoSettings, domain, includeDetails) {
|
|
574
|
+
if (gpoSettings && gpoSettings.ldapChannelBinding !== undefined) {
|
|
575
|
+
const bindingDisabled = gpoSettings.ldapChannelBinding === 0;
|
|
576
|
+
return {
|
|
577
|
+
type: 'LDAP_CHANNEL_BINDING_DISABLED',
|
|
578
|
+
severity: 'high',
|
|
579
|
+
category: 'advanced',
|
|
580
|
+
title: 'LDAP Channel Binding Not Required',
|
|
581
|
+
description: 'LDAP channel binding is not required. This allows NTLM relay attacks against LDAPS connections even when signing is enabled.',
|
|
582
|
+
count: bindingDisabled ? 1 : 0,
|
|
583
|
+
affectedEntities: includeDetails && bindingDisabled && domain ? [domain.dn] : undefined,
|
|
584
|
+
details: bindingDisabled
|
|
585
|
+
? {
|
|
586
|
+
recommendation: 'Configure "Domain controller: LDAP server channel binding token requirements" to "Always".',
|
|
587
|
+
currentSetting: gpoSettings.ldapChannelBinding,
|
|
588
|
+
requiredSetting: 2,
|
|
589
|
+
}
|
|
590
|
+
: undefined,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
type: 'LDAP_CHANNEL_BINDING_DISABLED',
|
|
595
|
+
severity: 'high',
|
|
596
|
+
category: 'advanced',
|
|
597
|
+
title: 'LDAP Channel Binding Configuration Unknown',
|
|
598
|
+
description: 'Unable to determine LDAP channel binding configuration. Manual review recommended.',
|
|
599
|
+
count: 0,
|
|
600
|
+
details: {
|
|
601
|
+
note: 'GPO/Registry settings not available. Check LdapEnforceChannelBinding registry value manually.',
|
|
602
|
+
},
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
function detectSmbV1Enabled(gpoSettings, domain, includeDetails) {
|
|
606
|
+
if (gpoSettings && (gpoSettings.smbv1ServerEnabled !== undefined || gpoSettings.smbv1ClientEnabled !== undefined)) {
|
|
607
|
+
const smbv1Enabled = gpoSettings.smbv1ServerEnabled === true || gpoSettings.smbv1ClientEnabled === true;
|
|
608
|
+
return {
|
|
609
|
+
type: 'SMB_V1_ENABLED',
|
|
610
|
+
severity: 'high',
|
|
611
|
+
category: 'advanced',
|
|
612
|
+
title: 'SMBv1 Protocol Enabled',
|
|
613
|
+
description: 'SMBv1 protocol is enabled. SMBv1 is deprecated and vulnerable to attacks like EternalBlue (WannaCry, NotPetya).',
|
|
614
|
+
count: smbv1Enabled ? 1 : 0,
|
|
615
|
+
affectedEntities: includeDetails && smbv1Enabled && domain ? [domain.dn] : undefined,
|
|
616
|
+
details: smbv1Enabled
|
|
617
|
+
? {
|
|
618
|
+
recommendation: 'Disable SMBv1 on all systems. Use SMBv2/v3 instead.',
|
|
619
|
+
smbv1Server: gpoSettings.smbv1ServerEnabled,
|
|
620
|
+
smbv1Client: gpoSettings.smbv1ClientEnabled,
|
|
621
|
+
}
|
|
622
|
+
: undefined,
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
type: 'SMB_V1_ENABLED',
|
|
627
|
+
severity: 'high',
|
|
628
|
+
category: 'advanced',
|
|
629
|
+
title: 'SMBv1 Configuration Unknown',
|
|
630
|
+
description: 'Unable to determine SMBv1 configuration. Manual review recommended.',
|
|
631
|
+
count: 0,
|
|
632
|
+
details: {
|
|
633
|
+
note: 'GPO/Registry settings not available. Check SMB1 registry values and Windows features manually.',
|
|
634
|
+
},
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
function detectSmbSigningDisabled(gpoSettings, domain, includeDetails) {
|
|
638
|
+
if (gpoSettings && gpoSettings.smbSigningRequired !== undefined) {
|
|
639
|
+
const signingDisabled = gpoSettings.smbSigningRequired === false;
|
|
640
|
+
return {
|
|
641
|
+
type: 'SMB_SIGNING_DISABLED',
|
|
642
|
+
severity: 'critical',
|
|
643
|
+
category: 'advanced',
|
|
644
|
+
title: 'SMB Signing Not Required',
|
|
645
|
+
description: 'SMB server signing is not required. This allows man-in-the-middle attacks and NTLM relay attacks against SMB connections.',
|
|
646
|
+
count: signingDisabled ? 1 : 0,
|
|
647
|
+
affectedEntities: includeDetails && signingDisabled && domain ? [domain.dn] : undefined,
|
|
648
|
+
details: signingDisabled
|
|
649
|
+
? {
|
|
650
|
+
recommendation: 'Configure "Microsoft network server: Digitally sign communications (always)" to Enabled.',
|
|
651
|
+
currentSetting: 'Not Required',
|
|
652
|
+
requiredSetting: 'Required',
|
|
653
|
+
smbServerSigning: gpoSettings.smbSigningRequired,
|
|
654
|
+
smbClientSigning: gpoSettings.smbClientSigningRequired,
|
|
655
|
+
}
|
|
656
|
+
: undefined,
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
type: 'SMB_SIGNING_DISABLED',
|
|
661
|
+
severity: 'critical',
|
|
662
|
+
category: 'advanced',
|
|
663
|
+
title: 'SMB Signing Not Configured in GPO',
|
|
664
|
+
description: 'SMB signing is not configured via Group Policy. Windows defaults do not require SMB signing, making this environment vulnerable to NTLM relay attacks.',
|
|
665
|
+
count: 1,
|
|
666
|
+
affectedEntities: includeDetails && domain ? [domain.dn] : undefined,
|
|
667
|
+
details: {
|
|
668
|
+
recommendation: 'Configure "Microsoft network server: Digitally sign communications (always)" via Group Policy.',
|
|
669
|
+
note: 'No GPO security template found. Windows defaults do not require SMB signing.',
|
|
670
|
+
},
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
function detectAuditPolicyWeak(gpoSettings, domain, includeDetails) {
|
|
674
|
+
const criticalAuditCategories = [
|
|
675
|
+
'Account Logon',
|
|
676
|
+
'Account Management',
|
|
677
|
+
'Logon/Logoff',
|
|
678
|
+
'Object Access',
|
|
679
|
+
'Policy Change',
|
|
680
|
+
'Privilege Use',
|
|
681
|
+
'System',
|
|
682
|
+
];
|
|
683
|
+
if (gpoSettings && gpoSettings.auditPolicies && gpoSettings.auditPolicies.length > 0) {
|
|
684
|
+
const configuredCategories = new Set(gpoSettings.auditPolicies.map((p) => p.category));
|
|
685
|
+
const missingCategories = criticalAuditCategories.filter((cat) => !configuredCategories.has(cat));
|
|
686
|
+
const hasWeakAudit = missingCategories.length > 0;
|
|
687
|
+
return {
|
|
688
|
+
type: 'AUDIT_POLICY_WEAK',
|
|
689
|
+
severity: 'medium',
|
|
690
|
+
category: 'advanced',
|
|
691
|
+
title: 'Audit Policy Incomplete',
|
|
692
|
+
description: 'Domain audit policy does not cover all critical security events. Attacks may go undetected.',
|
|
693
|
+
count: hasWeakAudit ? 1 : 0,
|
|
694
|
+
affectedEntities: includeDetails && hasWeakAudit && domain ? [domain.dn] : undefined,
|
|
695
|
+
details: hasWeakAudit
|
|
696
|
+
? {
|
|
697
|
+
recommendation: 'Configure Advanced Audit Policy to audit all critical security categories.',
|
|
698
|
+
missingCategories,
|
|
699
|
+
configuredCategories: Array.from(configuredCategories),
|
|
700
|
+
}
|
|
701
|
+
: undefined,
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
type: 'AUDIT_POLICY_WEAK',
|
|
706
|
+
severity: 'medium',
|
|
707
|
+
category: 'advanced',
|
|
708
|
+
title: 'Audit Policy Configuration Unknown',
|
|
709
|
+
description: 'Unable to determine audit policy configuration. Manual review recommended.',
|
|
710
|
+
count: 0,
|
|
711
|
+
details: {
|
|
712
|
+
note: 'GPO audit settings not available. Check Advanced Audit Policy Configuration manually.',
|
|
713
|
+
requiredCategories: criticalAuditCategories,
|
|
714
|
+
},
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
function detectPowershellLoggingDisabled(gpoSettings, domain, includeDetails) {
|
|
718
|
+
if (gpoSettings && gpoSettings.powershellLogging) {
|
|
719
|
+
const logging = gpoSettings.powershellLogging;
|
|
720
|
+
const loggingDisabled = !logging.moduleLogging && !logging.scriptBlockLogging;
|
|
721
|
+
return {
|
|
722
|
+
type: 'POWERSHELL_LOGGING_DISABLED',
|
|
723
|
+
severity: 'medium',
|
|
724
|
+
category: 'advanced',
|
|
725
|
+
title: 'PowerShell Logging Not Configured',
|
|
726
|
+
description: 'PowerShell script block logging and module logging are not enabled. Malicious PowerShell activity will not be logged.',
|
|
727
|
+
count: loggingDisabled ? 1 : 0,
|
|
728
|
+
affectedEntities: includeDetails && loggingDisabled && domain ? [domain.dn] : undefined,
|
|
729
|
+
details: loggingDisabled
|
|
730
|
+
? {
|
|
731
|
+
recommendation: 'Enable "Turn on PowerShell Script Block Logging" and "Turn on Module Logging" via GPO.',
|
|
732
|
+
moduleLogging: logging.moduleLogging,
|
|
733
|
+
scriptBlockLogging: logging.scriptBlockLogging,
|
|
734
|
+
transcription: logging.transcription,
|
|
735
|
+
}
|
|
736
|
+
: undefined,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
return {
|
|
740
|
+
type: 'POWERSHELL_LOGGING_DISABLED',
|
|
741
|
+
severity: 'medium',
|
|
742
|
+
category: 'advanced',
|
|
743
|
+
title: 'PowerShell Logging Configuration Unknown',
|
|
744
|
+
description: 'Unable to determine PowerShell logging configuration. Manual review recommended.',
|
|
745
|
+
count: 0,
|
|
746
|
+
details: {
|
|
747
|
+
note: 'GPO/Registry settings not available. Check PowerShell logging GPO settings manually.',
|
|
748
|
+
},
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function detectDsHeuristicsModified(domain, _includeDetails) {
|
|
752
|
+
const dsHeuristics = domain ? domain['dsHeuristics'] : undefined;
|
|
753
|
+
const isModified = dsHeuristics !== undefined && dsHeuristics !== null && dsHeuristics !== '';
|
|
754
|
+
const dangerousSettings = [];
|
|
755
|
+
if (dsHeuristics) {
|
|
756
|
+
if (dsHeuristics.length >= 7 && dsHeuristics[6] === '2') {
|
|
757
|
+
dangerousSettings.push('Anonymous LDAP operations allowed (position 7)');
|
|
758
|
+
}
|
|
759
|
+
if (dsHeuristics.length >= 3 && dsHeuristics[2] === '1') {
|
|
760
|
+
dangerousSettings.push('List Object mode disabled (position 3)');
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return {
|
|
764
|
+
type: 'DS_HEURISTICS_MODIFIED',
|
|
765
|
+
severity: 'medium',
|
|
766
|
+
category: 'advanced',
|
|
767
|
+
title: 'dsHeuristics Modified',
|
|
768
|
+
description: 'The dsHeuristics attribute has been modified from defaults. ' +
|
|
769
|
+
'This may weaken AD security or enable dangerous features.',
|
|
770
|
+
count: isModified ? 1 : 0,
|
|
771
|
+
details: {
|
|
772
|
+
currentValue: dsHeuristics || '(empty)',
|
|
773
|
+
dangerousSettings: dangerousSettings.length > 0 ? dangerousSettings : undefined,
|
|
774
|
+
recommendation: 'Review dsHeuristics value and document any intentional modifications.',
|
|
775
|
+
},
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function detectAdminSdHolderModified(domain, _includeDetails) {
|
|
779
|
+
const adminSdHolderInfo = domain
|
|
780
|
+
? domain['adminSDHolderModified']
|
|
781
|
+
: undefined;
|
|
782
|
+
return {
|
|
783
|
+
type: 'ADMIN_SD_HOLDER_MODIFIED',
|
|
784
|
+
severity: 'high',
|
|
785
|
+
category: 'advanced',
|
|
786
|
+
title: 'AdminSDHolder Review Required',
|
|
787
|
+
description: 'AdminSDHolder permissions should be reviewed. Modifications propagate to all protected accounts ' +
|
|
788
|
+
'(Domain Admins, Enterprise Admins, etc.) via SDProp process.',
|
|
789
|
+
count: adminSdHolderInfo ? 1 : 0,
|
|
790
|
+
details: {
|
|
791
|
+
recommendation: 'Compare AdminSDHolder ACL against baseline. Look for non-standard principals with permissions.',
|
|
792
|
+
checkCommand: 'Get-ADObject "CN=AdminSDHolder,CN=System,DC=..." -Properties nTSecurityDescriptor',
|
|
793
|
+
},
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
function detectExchangePrivEscPath(users, includeDetails) {
|
|
797
|
+
const exchangeGroups = [
|
|
798
|
+
'Exchange Trusted Subsystem',
|
|
799
|
+
'Exchange Windows Permissions',
|
|
800
|
+
'Organization Management',
|
|
801
|
+
'Exchange Servers',
|
|
802
|
+
];
|
|
803
|
+
const affected = users.filter((u) => {
|
|
804
|
+
if (!u.enabled || !u.memberOf)
|
|
805
|
+
return false;
|
|
806
|
+
return u.memberOf.some((dn) => exchangeGroups.some((eg) => dn.toLowerCase().includes(eg.toLowerCase())));
|
|
807
|
+
});
|
|
808
|
+
return {
|
|
809
|
+
type: 'EXCHANGE_PRIV_ESC_PATH',
|
|
810
|
+
severity: 'critical',
|
|
811
|
+
category: 'advanced',
|
|
812
|
+
title: 'Exchange Privilege Escalation Risk',
|
|
813
|
+
description: 'Users in Exchange security groups with potentially dangerous permissions. ' +
|
|
814
|
+
'Exchange Trusted Subsystem has WriteDacl on domain by default (CVE-2019-1166).',
|
|
815
|
+
count: affected.length,
|
|
816
|
+
affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedUserEntities)(affected) : undefined,
|
|
817
|
+
details: {
|
|
818
|
+
exchangeGroups: exchangeGroups,
|
|
819
|
+
recommendation: 'Review Exchange group permissions on domain head. Apply PrivExchange mitigations.',
|
|
820
|
+
reference: 'CVE-2019-1166, PrivExchange',
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function detectAdvancedVulnerabilities(users, computers, domain, templates = [], cas = [], fsps = [], includeDetails, options = {}) {
|
|
825
|
+
const { gpoSettings = null, anonymousAccessAllowed = false } = options;
|
|
826
|
+
return [
|
|
827
|
+
detectShadowCredentials(users, includeDetails),
|
|
828
|
+
detectRbcdAbuse(users, includeDetails),
|
|
829
|
+
detectLdapSigningDisabled(gpoSettings, domain, includeDetails),
|
|
830
|
+
detectSmbSigningDisabled(gpoSettings, domain, includeDetails),
|
|
831
|
+
detectEsc1VulnerableTemplate(templates, includeDetails),
|
|
832
|
+
detectEsc2AnyPurpose(templates, includeDetails),
|
|
833
|
+
detectEsc3EnrollmentAgent(templates, includeDetails),
|
|
834
|
+
detectEsc4VulnerableTemplateAcl(templates, includeDetails),
|
|
835
|
+
detectEsc6EditfAttributeSubjectAltName2(cas, includeDetails),
|
|
836
|
+
detectLapsPasswordReadable(computers, includeDetails),
|
|
837
|
+
detectReplicationRights(users, includeDetails),
|
|
838
|
+
detectDcsyncCapable(users, includeDetails),
|
|
839
|
+
detectMachineAccountQuotaHigh(domain, includeDetails),
|
|
840
|
+
detectLdapChannelBindingDisabled(gpoSettings, domain, includeDetails),
|
|
841
|
+
detectSmbV1Enabled(gpoSettings, domain, includeDetails),
|
|
842
|
+
detectEsc8HttpEnrollment(cas, includeDetails),
|
|
843
|
+
detectLapsNotDeployed(computers, includeDetails),
|
|
844
|
+
detectLapsLegacyAttribute(computers, includeDetails),
|
|
845
|
+
detectDuplicateSpn(users, includeDetails),
|
|
846
|
+
detectWeakPasswordPolicy(domain, includeDetails),
|
|
847
|
+
detectWeakKerberosPolicy(domain, includeDetails),
|
|
848
|
+
detectMachineAccountQuotaAbuse(domain, includeDetails),
|
|
849
|
+
detectDelegationPrivilege(users, includeDetails),
|
|
850
|
+
detectForeignSecurityPrincipals(fsps, includeDetails),
|
|
851
|
+
detectNtlmRelayOpportunity(domain, includeDetails),
|
|
852
|
+
detectAdcsWeakPermissions(templates, includeDetails),
|
|
853
|
+
detectDangerousLogonScripts(users, includeDetails),
|
|
854
|
+
detectRecycleBinDisabled(domain, includeDetails),
|
|
855
|
+
detectAnonymousLdapAccess(anonymousAccessAllowed, domain, includeDetails),
|
|
856
|
+
detectAuditPolicyWeak(gpoSettings, domain, includeDetails),
|
|
857
|
+
detectPowershellLoggingDisabled(gpoSettings, domain, includeDetails),
|
|
858
|
+
detectLapsPasswordSet(computers, includeDetails),
|
|
859
|
+
detectLapsPasswordLeaked(computers, includeDetails),
|
|
860
|
+
detectDsHeuristicsModified(domain, includeDetails),
|
|
861
|
+
detectAdminSdHolderModified(domain, includeDetails),
|
|
862
|
+
detectExchangePrivEscPath(users, includeDetails),
|
|
863
|
+
].filter((finding) => finding.count > 0 ||
|
|
864
|
+
finding.type === 'SMB_SIGNING_DISABLED' ||
|
|
865
|
+
finding.type === 'LDAP_SIGNING_DISABLED');
|
|
866
|
+
}
|
|
867
|
+
//# sourceMappingURL=advanced.detector.js.map
|