@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,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GPO Security Vulnerability Detector
|
|
3
|
+
*
|
|
4
|
+
* Analyzes Group Policy Objects for security misconfigurations.
|
|
5
|
+
*
|
|
6
|
+
* Vulnerabilities detected (9):
|
|
7
|
+
* CRITICAL (1) - Phase 4:
|
|
8
|
+
* - GPO_PASSWORD_IN_SYSVOL: Passwords found in GPO preferences
|
|
9
|
+
*
|
|
10
|
+
* HIGH (2):
|
|
11
|
+
* - GPO_DANGEROUS_PERMISSIONS: Non-admin can edit GPO linked to sensitive OUs
|
|
12
|
+
* - GPO_WEAK_PASSWORD_POLICY: GPO with password length < 12 characters
|
|
13
|
+
*
|
|
14
|
+
* MEDIUM (5):
|
|
15
|
+
* - GPO_LAPS_NOT_DEPLOYED: No LAPS deployment GPO found
|
|
16
|
+
* - GPO_DISABLED_BUT_LINKED: GPO disabled but still linked
|
|
17
|
+
* - GPO_NO_SECURITY_FILTERING: GPO without security filtering
|
|
18
|
+
* - GPO_AUTHENTICATED_USERS_APPLY: GPO applies to all Authenticated Users
|
|
19
|
+
* - GPO_ORPHANED: Orphaned GPO (Phase 4)
|
|
20
|
+
*
|
|
21
|
+
* LOW (1):
|
|
22
|
+
* - GPO_UNLINKED: GPO exists but not linked anywhere
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { Finding } from '../../../../types/finding.types';
|
|
26
|
+
import {
|
|
27
|
+
ADGPO,
|
|
28
|
+
GPOLink,
|
|
29
|
+
GPOAclEntry,
|
|
30
|
+
GPO_FLAG_ALL_DISABLED,
|
|
31
|
+
LAPS_CSE_GUID,
|
|
32
|
+
LAPS_LEGACY_CSE_GUID,
|
|
33
|
+
} from '../../../../types/gpo.types';
|
|
34
|
+
|
|
35
|
+
// Well-known SIDs for security filtering analysis
|
|
36
|
+
const SID_AUTHENTICATED_USERS = 'S-1-5-11';
|
|
37
|
+
const SID_EVERYONE = 'S-1-1-0';
|
|
38
|
+
const SID_DOMAIN_COMPUTERS = '-515'; // Ends with this RID
|
|
39
|
+
|
|
40
|
+
// "Apply Group Policy" extended right GUID
|
|
41
|
+
const APPLY_GROUP_POLICY_RIGHT = 0x00000004; // Read + Execute equivalent for GPO
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if GPO has LAPS Client-Side Extension
|
|
45
|
+
*/
|
|
46
|
+
function hasLapsCse(gpo: ADGPO): boolean {
|
|
47
|
+
const extensions = gpo.gPCMachineExtensionNames || '';
|
|
48
|
+
return extensions.includes(LAPS_CSE_GUID) || extensions.includes(LAPS_LEGACY_CSE_GUID);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* GPO_DANGEROUS_PERMISSIONS: Non-admin can edit GPO
|
|
53
|
+
* Note: Requires ACL analysis - placeholder for now
|
|
54
|
+
*/
|
|
55
|
+
export function detectGpoDangerousPermissions(
|
|
56
|
+
gpos: ADGPO[],
|
|
57
|
+
_links: GPOLink[],
|
|
58
|
+
_includeDetails: boolean
|
|
59
|
+
): Finding {
|
|
60
|
+
// Would analyze nTSecurityDescriptor on GPO objects for:
|
|
61
|
+
// - GenericAll, GenericWrite, WriteDacl, WriteOwner, WriteProperty
|
|
62
|
+
// granted to non-admin principals (Domain Users, Authenticated Users, etc.)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
type: 'GPO_DANGEROUS_PERMISSIONS',
|
|
66
|
+
severity: 'high',
|
|
67
|
+
category: 'gpo',
|
|
68
|
+
title: 'GPO Permissions Review Required',
|
|
69
|
+
description:
|
|
70
|
+
'Group Policy Objects should be reviewed for overly permissive ACLs that allow non-administrators to modify GPO settings.',
|
|
71
|
+
count: 0, // Placeholder until ACL analysis implemented
|
|
72
|
+
affectedEntities: undefined,
|
|
73
|
+
details: {
|
|
74
|
+
note: 'Manual review of GPO ACLs recommended. Check for non-admin principals with write access.',
|
|
75
|
+
gposToReview: gpos.length,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* GPO_LAPS_NOT_DEPLOYED: No LAPS deployment GPO found
|
|
82
|
+
*/
|
|
83
|
+
export function detectGpoLapsNotDeployed(
|
|
84
|
+
gpos: ADGPO[],
|
|
85
|
+
links: GPOLink[],
|
|
86
|
+
_includeDetails: boolean
|
|
87
|
+
): Finding {
|
|
88
|
+
// Check if any GPO has LAPS CSE and is linked
|
|
89
|
+
const lapsGpos = gpos.filter((gpo) => hasLapsCse(gpo));
|
|
90
|
+
const linkedLapsGpos = lapsGpos.filter((gpo) =>
|
|
91
|
+
links.some((link) => link.gpoGuid.toLowerCase() === gpo.cn.toLowerCase() && !link.disabled)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const noLapsDeployed = linkedLapsGpos.length === 0;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
type: 'GPO_LAPS_NOT_DEPLOYED',
|
|
98
|
+
severity: 'medium',
|
|
99
|
+
category: 'gpo',
|
|
100
|
+
title: 'LAPS Not Deployed via GPO',
|
|
101
|
+
description:
|
|
102
|
+
'No active Group Policy Object was found deploying LAPS (Local Administrator Password Solution). This leaves local admin passwords vulnerable to reuse attacks.',
|
|
103
|
+
count: noLapsDeployed ? 1 : 0,
|
|
104
|
+
affectedEntities: undefined,
|
|
105
|
+
details: {
|
|
106
|
+
lapsGposFound: lapsGpos.length,
|
|
107
|
+
linkedLapsGpos: linkedLapsGpos.length,
|
|
108
|
+
note: noLapsDeployed
|
|
109
|
+
? 'LAPS not deployed - local admin passwords are not being rotated.'
|
|
110
|
+
: 'LAPS is deployed via GPO.',
|
|
111
|
+
recommendation: noLapsDeployed
|
|
112
|
+
? 'Deploy LAPS via GPO to manage local administrator passwords.'
|
|
113
|
+
: undefined,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* GPO_WEAK_PASSWORD_POLICY: GPO with weak password settings
|
|
120
|
+
* Note: Requires reading GptTmpl.inf via SMB - check domain policy instead
|
|
121
|
+
*/
|
|
122
|
+
export function detectGpoWeakPasswordPolicy(
|
|
123
|
+
_gpos: ADGPO[],
|
|
124
|
+
_links: GPOLink[],
|
|
125
|
+
domainPasswordPolicy: { minPasswordLength?: number } | null,
|
|
126
|
+
includeDetails: boolean
|
|
127
|
+
): Finding {
|
|
128
|
+
const minLength = domainPasswordPolicy?.minPasswordLength ?? 0;
|
|
129
|
+
const isWeak = minLength < 12;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
type: 'GPO_WEAK_PASSWORD_POLICY',
|
|
133
|
+
severity: 'medium',
|
|
134
|
+
category: 'gpo',
|
|
135
|
+
title: 'Weak Password Policy',
|
|
136
|
+
description: `Domain password policy requires only ${minLength} characters minimum. Microsoft recommends at least 12 characters for standard accounts, 14+ for privileged accounts.`,
|
|
137
|
+
count: isWeak ? 1 : 0,
|
|
138
|
+
affectedEntities: includeDetails && isWeak ? ['Default Domain Policy'] : undefined,
|
|
139
|
+
details: isWeak
|
|
140
|
+
? {
|
|
141
|
+
currentMinLength: minLength,
|
|
142
|
+
recommendedMinLength: 12,
|
|
143
|
+
}
|
|
144
|
+
: undefined,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* GPO_UNLINKED: GPO exists but not linked anywhere
|
|
150
|
+
*/
|
|
151
|
+
export function detectGpoUnlinked(
|
|
152
|
+
gpos: ADGPO[],
|
|
153
|
+
links: GPOLink[],
|
|
154
|
+
includeDetails: boolean
|
|
155
|
+
): Finding {
|
|
156
|
+
// Find GPOs that have no links
|
|
157
|
+
const linkedGuids = new Set(links.map((l) => l.gpoGuid.toLowerCase()));
|
|
158
|
+
const unlinkedGpos = gpos.filter((gpo) => !linkedGuids.has(gpo.cn.toLowerCase()));
|
|
159
|
+
|
|
160
|
+
// Exclude Default Domain Policy and Default Domain Controllers Policy
|
|
161
|
+
const excludeGuids = [
|
|
162
|
+
'31B2F340-016D-11D2-945F-00C04FB984F9', // Default Domain Policy
|
|
163
|
+
'6AC1786C-016F-11D2-945F-00C04FB984F9', // Default Domain Controllers Policy
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
const relevantUnlinked = unlinkedGpos.filter(
|
|
167
|
+
(gpo) => !excludeGuids.some((guid) => gpo.cn.toUpperCase().includes(guid))
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
type: 'GPO_UNLINKED',
|
|
172
|
+
severity: 'low',
|
|
173
|
+
category: 'gpo',
|
|
174
|
+
title: 'Unlinked Group Policy Objects',
|
|
175
|
+
description:
|
|
176
|
+
'GPOs exist that are not linked to any OU, domain, or site. These may be orphaned or indicate incomplete deployment.',
|
|
177
|
+
count: relevantUnlinked.length,
|
|
178
|
+
affectedEntities: includeDetails
|
|
179
|
+
? relevantUnlinked.map((gpo) => gpo.displayName || gpo.cn)
|
|
180
|
+
: undefined,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* GPO_DISABLED_BUT_LINKED: GPO is disabled but still linked
|
|
186
|
+
*/
|
|
187
|
+
export function detectGpoDisabledButLinked(
|
|
188
|
+
gpos: ADGPO[],
|
|
189
|
+
links: GPOLink[],
|
|
190
|
+
includeDetails: boolean
|
|
191
|
+
): Finding {
|
|
192
|
+
// Find GPOs that are disabled (flags = 3) but have active links
|
|
193
|
+
const disabledGpos = gpos.filter((gpo) => gpo.flags === GPO_FLAG_ALL_DISABLED);
|
|
194
|
+
|
|
195
|
+
const disabledButLinked = disabledGpos.filter((gpo) =>
|
|
196
|
+
links.some((link) => link.gpoGuid.toLowerCase() === gpo.cn.toLowerCase() && !link.disabled)
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
type: 'GPO_DISABLED_BUT_LINKED',
|
|
201
|
+
severity: 'medium',
|
|
202
|
+
category: 'gpo',
|
|
203
|
+
title: 'Disabled GPO Still Linked',
|
|
204
|
+
description:
|
|
205
|
+
'GPOs are disabled (both user and computer settings) but remain linked. This may indicate configuration drift or incomplete changes.',
|
|
206
|
+
count: disabledButLinked.length,
|
|
207
|
+
affectedEntities: includeDetails
|
|
208
|
+
? disabledButLinked.map((gpo) => gpo.displayName || gpo.cn)
|
|
209
|
+
: undefined,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* GPO_NO_SECURITY_FILTERING: GPO without explicit security filtering
|
|
215
|
+
* GPO applies to all objects in the linked OU without restrictions
|
|
216
|
+
*/
|
|
217
|
+
export function detectGpoNoSecurityFiltering(
|
|
218
|
+
gpos: ADGPO[],
|
|
219
|
+
links: GPOLink[],
|
|
220
|
+
gpoAcls: GPOAclEntry[],
|
|
221
|
+
includeDetails: boolean
|
|
222
|
+
): Finding {
|
|
223
|
+
// Get linked GPO GUIDs
|
|
224
|
+
const linkedGuids = new Set(
|
|
225
|
+
links.filter((l) => !l.disabled).map((l) => l.gpoGuid.toLowerCase())
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Find GPOs that are linked but have no security filtering
|
|
229
|
+
// Security filtering = only specific groups have "Apply Group Policy" right
|
|
230
|
+
// No filtering = Authenticated Users or Everyone has Apply right
|
|
231
|
+
const noFiltering: ADGPO[] = [];
|
|
232
|
+
|
|
233
|
+
for (const gpo of gpos) {
|
|
234
|
+
// Only check linked GPOs
|
|
235
|
+
if (!linkedGuids.has(gpo.cn.toLowerCase())) continue;
|
|
236
|
+
|
|
237
|
+
// Get ACLs for this GPO
|
|
238
|
+
const aclsForGpo = gpoAcls.filter(
|
|
239
|
+
(acl) => acl.gpoDn.toLowerCase() === gpo.dn.toLowerCase()
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// If no ACL data, skip (can't determine)
|
|
243
|
+
if (aclsForGpo.length === 0) continue;
|
|
244
|
+
|
|
245
|
+
// Check if Authenticated Users or Everyone has Apply permission
|
|
246
|
+
const hasUnrestrictedApply = aclsForGpo.some(
|
|
247
|
+
(acl) =>
|
|
248
|
+
(acl.trusteeSid === SID_AUTHENTICATED_USERS || acl.trusteeSid === SID_EVERYONE) &&
|
|
249
|
+
(acl.accessMask & APPLY_GROUP_POLICY_RIGHT) !== 0
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// Check if there's any specific group filtering (exclude auth users and everyone)
|
|
253
|
+
const hasSpecificFiltering = aclsForGpo.some(
|
|
254
|
+
(acl) =>
|
|
255
|
+
acl.trusteeSid !== SID_AUTHENTICATED_USERS &&
|
|
256
|
+
acl.trusteeSid !== SID_EVERYONE &&
|
|
257
|
+
!acl.trusteeSid.endsWith(SID_DOMAIN_COMPUTERS) &&
|
|
258
|
+
(acl.accessMask & APPLY_GROUP_POLICY_RIGHT) !== 0
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
// No filtering if auth users/everyone can apply and no specific groups defined
|
|
262
|
+
if (hasUnrestrictedApply && !hasSpecificFiltering) {
|
|
263
|
+
noFiltering.push(gpo);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
type: 'GPO_NO_SECURITY_FILTERING',
|
|
269
|
+
severity: 'medium',
|
|
270
|
+
category: 'gpo',
|
|
271
|
+
title: 'GPO Without Security Filtering',
|
|
272
|
+
description:
|
|
273
|
+
'GPOs that apply to all Authenticated Users or Everyone without specific security filtering. Consider restricting GPO application to specific groups.',
|
|
274
|
+
count: noFiltering.length,
|
|
275
|
+
affectedEntities: includeDetails
|
|
276
|
+
? noFiltering.map((gpo) => gpo.displayName || gpo.cn)
|
|
277
|
+
: undefined,
|
|
278
|
+
details:
|
|
279
|
+
noFiltering.length > 0
|
|
280
|
+
? {
|
|
281
|
+
recommendation:
|
|
282
|
+
'Apply security filtering to restrict GPO application to specific groups.',
|
|
283
|
+
}
|
|
284
|
+
: undefined,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* GPO_AUTHENTICATED_USERS_APPLY: GPO explicitly grants Apply to Authenticated Users
|
|
290
|
+
* This is the default but may be unintended for sensitive GPOs
|
|
291
|
+
*/
|
|
292
|
+
export function detectGpoAuthenticatedUsersApply(
|
|
293
|
+
gpos: ADGPO[],
|
|
294
|
+
links: GPOLink[],
|
|
295
|
+
gpoAcls: GPOAclEntry[],
|
|
296
|
+
includeDetails: boolean
|
|
297
|
+
): Finding {
|
|
298
|
+
// Get linked GPO GUIDs
|
|
299
|
+
const linkedGuids = new Set(
|
|
300
|
+
links.filter((l) => !l.disabled).map((l) => l.gpoGuid.toLowerCase())
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// Find GPOs where Authenticated Users has explicit Apply permission
|
|
304
|
+
const authUsersApply: ADGPO[] = [];
|
|
305
|
+
|
|
306
|
+
for (const gpo of gpos) {
|
|
307
|
+
// Only check linked GPOs
|
|
308
|
+
if (!linkedGuids.has(gpo.cn.toLowerCase())) continue;
|
|
309
|
+
|
|
310
|
+
// Get ACLs for this GPO
|
|
311
|
+
const aclsForGpo = gpoAcls.filter(
|
|
312
|
+
(acl) => acl.gpoDn.toLowerCase() === gpo.dn.toLowerCase()
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// If no ACL data, skip
|
|
316
|
+
if (aclsForGpo.length === 0) continue;
|
|
317
|
+
|
|
318
|
+
// Check if Authenticated Users specifically has Apply permission
|
|
319
|
+
const authUsersHasApply = aclsForGpo.some(
|
|
320
|
+
(acl) =>
|
|
321
|
+
acl.trusteeSid === SID_AUTHENTICATED_USERS &&
|
|
322
|
+
(acl.accessMask & APPLY_GROUP_POLICY_RIGHT) !== 0
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
if (authUsersHasApply) {
|
|
326
|
+
authUsersApply.push(gpo);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
type: 'GPO_AUTHENTICATED_USERS_APPLY',
|
|
332
|
+
severity: 'medium',
|
|
333
|
+
category: 'gpo',
|
|
334
|
+
title: 'GPO Applies to All Authenticated Users',
|
|
335
|
+
description:
|
|
336
|
+
'GPOs with Authenticated Users granted the "Apply Group Policy" permission. This is the default but may be too broad for sensitive policies.',
|
|
337
|
+
count: authUsersApply.length,
|
|
338
|
+
affectedEntities: includeDetails
|
|
339
|
+
? authUsersApply.map((gpo) => gpo.displayName || gpo.cn)
|
|
340
|
+
: undefined,
|
|
341
|
+
details:
|
|
342
|
+
authUsersApply.length > 0
|
|
343
|
+
? {
|
|
344
|
+
recommendation:
|
|
345
|
+
'Review if all GPOs should apply to all users. Consider using security filtering for sensitive policies.',
|
|
346
|
+
note: 'This is informational - Authenticated Users is the default.',
|
|
347
|
+
}
|
|
348
|
+
: undefined,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Detect GPOs with passwords stored in SYSVOL (cPassword)
|
|
354
|
+
*
|
|
355
|
+
* MS14-025 patched this, but old GPOs may still contain cleartext passwords
|
|
356
|
+
* in Groups.xml, Services.xml, Scheduledtasks.xml, etc.
|
|
357
|
+
*
|
|
358
|
+
* @param gpos - Array of GPOs
|
|
359
|
+
* @param _links - Array of GPO links (not used)
|
|
360
|
+
* @param includeDetails - Whether to include affected entity details
|
|
361
|
+
* @returns Finding for GPO_PASSWORD_IN_SYSVOL
|
|
362
|
+
*/
|
|
363
|
+
export function detectGpoPasswordInSysvol(
|
|
364
|
+
gpos: ADGPO[],
|
|
365
|
+
_links: GPOLink[],
|
|
366
|
+
includeDetails: boolean
|
|
367
|
+
): Finding {
|
|
368
|
+
// Check GPO flags or attributes that might indicate password presence
|
|
369
|
+
// This would ideally need SYSVOL file content reading
|
|
370
|
+
// For now, check for GPOs with "cpassword" mentioned or old-style preferences
|
|
371
|
+
const affected = gpos.filter((gpo) => {
|
|
372
|
+
const gpoName = (gpo.displayName || gpo.cn || '').toLowerCase();
|
|
373
|
+
const gpoPath = (gpo.gPCFileSysPath || '').toLowerCase();
|
|
374
|
+
|
|
375
|
+
// GPOs that commonly contain passwords
|
|
376
|
+
const riskyPatterns = [
|
|
377
|
+
'password',
|
|
378
|
+
'credential',
|
|
379
|
+
'local admin',
|
|
380
|
+
'service account',
|
|
381
|
+
'scheduled task',
|
|
382
|
+
'drive map',
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
return riskyPatterns.some(
|
|
386
|
+
(pattern) => gpoName.includes(pattern) || gpoPath.includes(pattern)
|
|
387
|
+
);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
type: 'GPO_PASSWORD_IN_SYSVOL',
|
|
392
|
+
severity: 'critical',
|
|
393
|
+
category: 'gpo',
|
|
394
|
+
title: 'Potential Passwords in GPO SYSVOL',
|
|
395
|
+
description:
|
|
396
|
+
'GPOs that may contain cleartext passwords in SYSVOL (cPassword vulnerability MS14-025). ' +
|
|
397
|
+
'Group Policy Preferences stored passwords that can be easily decrypted.',
|
|
398
|
+
count: affected.length,
|
|
399
|
+
affectedEntities: includeDetails
|
|
400
|
+
? affected.map((g) => g.displayName || g.cn || g.dn)
|
|
401
|
+
: undefined,
|
|
402
|
+
details: {
|
|
403
|
+
note: affected.length > 0
|
|
404
|
+
? `Found ${affected.length} GPO(s) with names suggesting password storage. Manual SYSVOL scan required.`
|
|
405
|
+
: 'No GPOs with suspicious names found. Manual SYSVOL scan still recommended.',
|
|
406
|
+
recommendation:
|
|
407
|
+
'Scan SYSVOL for Groups.xml, Services.xml, ScheduledTasks.xml, DataSources.xml containing cpassword. ' +
|
|
408
|
+
'Use tools like Get-GPPPassword or gpp-decrypt.',
|
|
409
|
+
reference: 'MS14-025',
|
|
410
|
+
gposScanned: gpos.length,
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Detect orphaned GPOs
|
|
417
|
+
*
|
|
418
|
+
* GPOs that exist in AD but have missing SYSVOL content, or vice versa.
|
|
419
|
+
*
|
|
420
|
+
* @param gpos - Array of GPOs
|
|
421
|
+
* @param _links - Array of GPO links (not used)
|
|
422
|
+
* @param includeDetails - Whether to include affected entity details
|
|
423
|
+
* @returns Finding for GPO_ORPHANED
|
|
424
|
+
*/
|
|
425
|
+
export function detectGpoOrphaned(
|
|
426
|
+
gpos: ADGPO[],
|
|
427
|
+
_links: GPOLink[],
|
|
428
|
+
includeDetails: boolean
|
|
429
|
+
): Finding {
|
|
430
|
+
// Check for GPOs with potential orphan indicators
|
|
431
|
+
// A proper check would compare AD GPOs vs SYSVOL folders
|
|
432
|
+
const affected = gpos.filter((gpo) => {
|
|
433
|
+
// Missing SYSVOL path indicates potential orphan
|
|
434
|
+
const hasSysvolPath = gpo.gPCFileSysPath && gpo.gPCFileSysPath.length > 0;
|
|
435
|
+
// Missing version might indicate corruption
|
|
436
|
+
const hasVersion = gpo.versionNumber !== undefined && gpo.versionNumber > 0;
|
|
437
|
+
// Check for obviously broken GPOs
|
|
438
|
+
const hasName = gpo.displayName || gpo.cn;
|
|
439
|
+
|
|
440
|
+
return !hasSysvolPath || !hasVersion || !hasName;
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
return {
|
|
444
|
+
type: 'GPO_ORPHANED',
|
|
445
|
+
severity: 'medium',
|
|
446
|
+
category: 'gpo',
|
|
447
|
+
title: 'Potentially Orphaned GPOs',
|
|
448
|
+
description:
|
|
449
|
+
'GPOs that may be orphaned (missing SYSVOL content or AD object). ' +
|
|
450
|
+
'Orphaned GPOs can cause processing errors and may indicate tampering.',
|
|
451
|
+
count: affected.length,
|
|
452
|
+
affectedEntities: includeDetails
|
|
453
|
+
? affected.map((g) => g.displayName || g.cn || g.dn)
|
|
454
|
+
: undefined,
|
|
455
|
+
details: {
|
|
456
|
+
recommendation:
|
|
457
|
+
'Compare AD GPOs with SYSVOL folders. Use gpotool.exe or Get-GPO to identify orphans. ' +
|
|
458
|
+
'Delete orphaned GPOs after verification.',
|
|
459
|
+
},
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Aggregate function: Detect all GPO vulnerabilities
|
|
465
|
+
*/
|
|
466
|
+
export function detectGpoVulnerabilities(
|
|
467
|
+
gpos: ADGPO[],
|
|
468
|
+
links: GPOLink[],
|
|
469
|
+
domainPasswordPolicy: { minPasswordLength?: number } | null,
|
|
470
|
+
includeDetails: boolean,
|
|
471
|
+
gpoAcls: GPOAclEntry[] = []
|
|
472
|
+
): Finding[] {
|
|
473
|
+
return [
|
|
474
|
+
detectGpoDangerousPermissions(gpos, links, includeDetails),
|
|
475
|
+
detectGpoLapsNotDeployed(gpos, links, includeDetails),
|
|
476
|
+
detectGpoWeakPasswordPolicy(gpos, links, domainPasswordPolicy, includeDetails),
|
|
477
|
+
detectGpoUnlinked(gpos, links, includeDetails),
|
|
478
|
+
detectGpoDisabledButLinked(gpos, links, includeDetails),
|
|
479
|
+
detectGpoNoSecurityFiltering(gpos, links, gpoAcls, includeDetails),
|
|
480
|
+
detectGpoAuthenticatedUsersApply(gpos, links, gpoAcls, includeDetails),
|
|
481
|
+
// Phase 4: Advanced GPO detections
|
|
482
|
+
detectGpoPasswordInSysvol(gpos, links, includeDetails),
|
|
483
|
+
detectGpoOrphaned(gpos, links, includeDetails),
|
|
484
|
+
].filter((finding) => finding.count > 0 || finding.details?.['note']);
|
|
485
|
+
}
|