@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.
Files changed (617) hide show
  1. package/.env.example +60 -0
  2. package/.env.test.example +33 -0
  3. package/.github/workflows/ci.yml +83 -0
  4. package/.github/workflows/release.yml +246 -0
  5. package/.prettierrc.json +10 -0
  6. package/CHANGELOG.md +15 -0
  7. package/Dockerfile +57 -0
  8. package/LICENSE +190 -0
  9. package/README.md +194 -0
  10. package/dist/api/controllers/audit.controller.d.ts +21 -0
  11. package/dist/api/controllers/audit.controller.d.ts.map +1 -0
  12. package/dist/api/controllers/audit.controller.js +179 -0
  13. package/dist/api/controllers/audit.controller.js.map +1 -0
  14. package/dist/api/controllers/auth.controller.d.ts +16 -0
  15. package/dist/api/controllers/auth.controller.d.ts.map +1 -0
  16. package/dist/api/controllers/auth.controller.js +146 -0
  17. package/dist/api/controllers/auth.controller.js.map +1 -0
  18. package/dist/api/controllers/export.controller.d.ts +27 -0
  19. package/dist/api/controllers/export.controller.d.ts.map +1 -0
  20. package/dist/api/controllers/export.controller.js +80 -0
  21. package/dist/api/controllers/export.controller.js.map +1 -0
  22. package/dist/api/controllers/health.controller.d.ts +5 -0
  23. package/dist/api/controllers/health.controller.d.ts.map +1 -0
  24. package/dist/api/controllers/health.controller.js +16 -0
  25. package/dist/api/controllers/health.controller.js.map +1 -0
  26. package/dist/api/controllers/jobs.controller.d.ts +13 -0
  27. package/dist/api/controllers/jobs.controller.d.ts.map +1 -0
  28. package/dist/api/controllers/jobs.controller.js +125 -0
  29. package/dist/api/controllers/jobs.controller.js.map +1 -0
  30. package/dist/api/controllers/providers.controller.d.ts +15 -0
  31. package/dist/api/controllers/providers.controller.d.ts.map +1 -0
  32. package/dist/api/controllers/providers.controller.js +112 -0
  33. package/dist/api/controllers/providers.controller.js.map +1 -0
  34. package/dist/api/dto/AuditRequest.dto.d.ts +6 -0
  35. package/dist/api/dto/AuditRequest.dto.d.ts.map +1 -0
  36. package/dist/api/dto/AuditRequest.dto.js +3 -0
  37. package/dist/api/dto/AuditRequest.dto.js.map +1 -0
  38. package/dist/api/dto/AuditResponse.dto.d.ts +17 -0
  39. package/dist/api/dto/AuditResponse.dto.d.ts.map +1 -0
  40. package/dist/api/dto/AuditResponse.dto.js +3 -0
  41. package/dist/api/dto/AuditResponse.dto.js.map +1 -0
  42. package/dist/api/dto/TokenRequest.dto.d.ts +6 -0
  43. package/dist/api/dto/TokenRequest.dto.d.ts.map +1 -0
  44. package/dist/api/dto/TokenRequest.dto.js +3 -0
  45. package/dist/api/dto/TokenRequest.dto.js.map +1 -0
  46. package/dist/api/dto/TokenResponse.dto.d.ts +12 -0
  47. package/dist/api/dto/TokenResponse.dto.d.ts.map +1 -0
  48. package/dist/api/dto/TokenResponse.dto.js +3 -0
  49. package/dist/api/dto/TokenResponse.dto.js.map +1 -0
  50. package/dist/api/middlewares/authenticate.d.ts +12 -0
  51. package/dist/api/middlewares/authenticate.d.ts.map +1 -0
  52. package/dist/api/middlewares/authenticate.js +141 -0
  53. package/dist/api/middlewares/authenticate.js.map +1 -0
  54. package/dist/api/middlewares/errorHandler.d.ts +3 -0
  55. package/dist/api/middlewares/errorHandler.d.ts.map +1 -0
  56. package/dist/api/middlewares/errorHandler.js +30 -0
  57. package/dist/api/middlewares/errorHandler.js.map +1 -0
  58. package/dist/api/middlewares/rateLimit.d.ts +3 -0
  59. package/dist/api/middlewares/rateLimit.d.ts.map +1 -0
  60. package/dist/api/middlewares/rateLimit.js +34 -0
  61. package/dist/api/middlewares/rateLimit.js.map +1 -0
  62. package/dist/api/middlewares/validate.d.ts +4 -0
  63. package/dist/api/middlewares/validate.d.ts.map +1 -0
  64. package/dist/api/middlewares/validate.js +31 -0
  65. package/dist/api/middlewares/validate.js.map +1 -0
  66. package/dist/api/routes/audit.routes.d.ts +5 -0
  67. package/dist/api/routes/audit.routes.d.ts.map +1 -0
  68. package/dist/api/routes/audit.routes.js +24 -0
  69. package/dist/api/routes/audit.routes.js.map +1 -0
  70. package/dist/api/routes/auth.routes.d.ts +6 -0
  71. package/dist/api/routes/auth.routes.d.ts.map +1 -0
  72. package/dist/api/routes/auth.routes.js +22 -0
  73. package/dist/api/routes/auth.routes.js.map +1 -0
  74. package/dist/api/routes/export.routes.d.ts +5 -0
  75. package/dist/api/routes/export.routes.d.ts.map +1 -0
  76. package/dist/api/routes/export.routes.js +16 -0
  77. package/dist/api/routes/export.routes.js.map +1 -0
  78. package/dist/api/routes/health.routes.d.ts +4 -0
  79. package/dist/api/routes/health.routes.d.ts.map +1 -0
  80. package/dist/api/routes/health.routes.js +11 -0
  81. package/dist/api/routes/health.routes.js.map +1 -0
  82. package/dist/api/routes/index.d.ts +10 -0
  83. package/dist/api/routes/index.d.ts.map +1 -0
  84. package/dist/api/routes/index.js +20 -0
  85. package/dist/api/routes/index.js.map +1 -0
  86. package/dist/api/routes/providers.routes.d.ts +5 -0
  87. package/dist/api/routes/providers.routes.d.ts.map +1 -0
  88. package/dist/api/routes/providers.routes.js +13 -0
  89. package/dist/api/routes/providers.routes.js.map +1 -0
  90. package/dist/api/validators/audit.schemas.d.ts +60 -0
  91. package/dist/api/validators/audit.schemas.d.ts.map +1 -0
  92. package/dist/api/validators/audit.schemas.js +55 -0
  93. package/dist/api/validators/audit.schemas.js.map +1 -0
  94. package/dist/api/validators/auth.schemas.d.ts +17 -0
  95. package/dist/api/validators/auth.schemas.d.ts.map +1 -0
  96. package/dist/api/validators/auth.schemas.js +21 -0
  97. package/dist/api/validators/auth.schemas.js.map +1 -0
  98. package/dist/app.d.ts +3 -0
  99. package/dist/app.d.ts.map +1 -0
  100. package/dist/app.js +62 -0
  101. package/dist/app.js.map +1 -0
  102. package/dist/config/config.schema.d.ts +65 -0
  103. package/dist/config/config.schema.d.ts.map +1 -0
  104. package/dist/config/config.schema.js +95 -0
  105. package/dist/config/config.schema.js.map +1 -0
  106. package/dist/config/index.d.ts +4 -0
  107. package/dist/config/index.d.ts.map +1 -0
  108. package/dist/config/index.js +75 -0
  109. package/dist/config/index.js.map +1 -0
  110. package/dist/container.d.ts +47 -0
  111. package/dist/container.d.ts.map +1 -0
  112. package/dist/container.js +137 -0
  113. package/dist/container.js.map +1 -0
  114. package/dist/data/database.d.ts +13 -0
  115. package/dist/data/database.d.ts.map +1 -0
  116. package/dist/data/database.js +68 -0
  117. package/dist/data/database.js.map +1 -0
  118. package/dist/data/jobs/token-cleanup.job.d.ts +23 -0
  119. package/dist/data/jobs/token-cleanup.job.d.ts.map +1 -0
  120. package/dist/data/jobs/token-cleanup.job.js +96 -0
  121. package/dist/data/jobs/token-cleanup.job.js.map +1 -0
  122. package/dist/data/migrations/migration.runner.d.ts +13 -0
  123. package/dist/data/migrations/migration.runner.d.ts.map +1 -0
  124. package/dist/data/migrations/migration.runner.js +136 -0
  125. package/dist/data/migrations/migration.runner.js.map +1 -0
  126. package/dist/data/models/Token.model.d.ts +30 -0
  127. package/dist/data/models/Token.model.d.ts.map +1 -0
  128. package/dist/data/models/Token.model.js +3 -0
  129. package/dist/data/models/Token.model.js.map +1 -0
  130. package/dist/data/repositories/token.repository.d.ts +16 -0
  131. package/dist/data/repositories/token.repository.d.ts.map +1 -0
  132. package/dist/data/repositories/token.repository.js +97 -0
  133. package/dist/data/repositories/token.repository.js.map +1 -0
  134. package/dist/providers/azure/auth.provider.d.ts +5 -0
  135. package/dist/providers/azure/auth.provider.d.ts.map +1 -0
  136. package/dist/providers/azure/auth.provider.js +13 -0
  137. package/dist/providers/azure/auth.provider.js.map +1 -0
  138. package/dist/providers/azure/azure-errors.d.ts +40 -0
  139. package/dist/providers/azure/azure-errors.d.ts.map +1 -0
  140. package/dist/providers/azure/azure-errors.js +121 -0
  141. package/dist/providers/azure/azure-errors.js.map +1 -0
  142. package/dist/providers/azure/azure-retry.d.ts +41 -0
  143. package/dist/providers/azure/azure-retry.d.ts.map +1 -0
  144. package/dist/providers/azure/azure-retry.js +85 -0
  145. package/dist/providers/azure/azure-retry.js.map +1 -0
  146. package/dist/providers/azure/graph-client.d.ts +26 -0
  147. package/dist/providers/azure/graph-client.d.ts.map +1 -0
  148. package/dist/providers/azure/graph-client.js +146 -0
  149. package/dist/providers/azure/graph-client.js.map +1 -0
  150. package/dist/providers/azure/graph.provider.d.ts +23 -0
  151. package/dist/providers/azure/graph.provider.d.ts.map +1 -0
  152. package/dist/providers/azure/graph.provider.js +161 -0
  153. package/dist/providers/azure/graph.provider.js.map +1 -0
  154. package/dist/providers/azure/queries/app.queries.d.ts +6 -0
  155. package/dist/providers/azure/queries/app.queries.d.ts.map +1 -0
  156. package/dist/providers/azure/queries/app.queries.js +9 -0
  157. package/dist/providers/azure/queries/app.queries.js.map +1 -0
  158. package/dist/providers/azure/queries/policy.queries.d.ts +6 -0
  159. package/dist/providers/azure/queries/policy.queries.d.ts.map +1 -0
  160. package/dist/providers/azure/queries/policy.queries.js +9 -0
  161. package/dist/providers/azure/queries/policy.queries.js.map +1 -0
  162. package/dist/providers/azure/queries/user.queries.d.ts +7 -0
  163. package/dist/providers/azure/queries/user.queries.d.ts.map +1 -0
  164. package/dist/providers/azure/queries/user.queries.js +10 -0
  165. package/dist/providers/azure/queries/user.queries.js.map +1 -0
  166. package/dist/providers/interfaces/IGraphProvider.d.ts +31 -0
  167. package/dist/providers/interfaces/IGraphProvider.d.ts.map +1 -0
  168. package/dist/providers/interfaces/IGraphProvider.js +3 -0
  169. package/dist/providers/interfaces/IGraphProvider.js.map +1 -0
  170. package/dist/providers/interfaces/ILDAPProvider.d.ts +37 -0
  171. package/dist/providers/interfaces/ILDAPProvider.d.ts.map +1 -0
  172. package/dist/providers/interfaces/ILDAPProvider.js +3 -0
  173. package/dist/providers/interfaces/ILDAPProvider.js.map +1 -0
  174. package/dist/providers/ldap/acl-parser.d.ts +8 -0
  175. package/dist/providers/ldap/acl-parser.d.ts.map +1 -0
  176. package/dist/providers/ldap/acl-parser.js +157 -0
  177. package/dist/providers/ldap/acl-parser.js.map +1 -0
  178. package/dist/providers/ldap/ad-mappers.d.ts +8 -0
  179. package/dist/providers/ldap/ad-mappers.d.ts.map +1 -0
  180. package/dist/providers/ldap/ad-mappers.js +162 -0
  181. package/dist/providers/ldap/ad-mappers.js.map +1 -0
  182. package/dist/providers/ldap/ldap-client.d.ts +33 -0
  183. package/dist/providers/ldap/ldap-client.d.ts.map +1 -0
  184. package/dist/providers/ldap/ldap-client.js +195 -0
  185. package/dist/providers/ldap/ldap-client.js.map +1 -0
  186. package/dist/providers/ldap/ldap-errors.d.ts +48 -0
  187. package/dist/providers/ldap/ldap-errors.d.ts.map +1 -0
  188. package/dist/providers/ldap/ldap-errors.js +120 -0
  189. package/dist/providers/ldap/ldap-errors.js.map +1 -0
  190. package/dist/providers/ldap/ldap-retry.d.ts +14 -0
  191. package/dist/providers/ldap/ldap-retry.d.ts.map +1 -0
  192. package/dist/providers/ldap/ldap-retry.js +102 -0
  193. package/dist/providers/ldap/ldap-retry.js.map +1 -0
  194. package/dist/providers/ldap/ldap-sanitizer.d.ts +12 -0
  195. package/dist/providers/ldap/ldap-sanitizer.d.ts.map +1 -0
  196. package/dist/providers/ldap/ldap-sanitizer.js +104 -0
  197. package/dist/providers/ldap/ldap-sanitizer.js.map +1 -0
  198. package/dist/providers/ldap/ldap.provider.d.ts +21 -0
  199. package/dist/providers/ldap/ldap.provider.d.ts.map +1 -0
  200. package/dist/providers/ldap/ldap.provider.js +165 -0
  201. package/dist/providers/ldap/ldap.provider.js.map +1 -0
  202. package/dist/providers/ldap/queries/computer.queries.d.ts +6 -0
  203. package/dist/providers/ldap/queries/computer.queries.d.ts.map +1 -0
  204. package/dist/providers/ldap/queries/computer.queries.js +9 -0
  205. package/dist/providers/ldap/queries/computer.queries.js.map +1 -0
  206. package/dist/providers/ldap/queries/group.queries.d.ts +6 -0
  207. package/dist/providers/ldap/queries/group.queries.d.ts.map +1 -0
  208. package/dist/providers/ldap/queries/group.queries.js +9 -0
  209. package/dist/providers/ldap/queries/group.queries.js.map +1 -0
  210. package/dist/providers/ldap/queries/user.queries.d.ts +7 -0
  211. package/dist/providers/ldap/queries/user.queries.d.ts.map +1 -0
  212. package/dist/providers/ldap/queries/user.queries.js +10 -0
  213. package/dist/providers/ldap/queries/user.queries.js.map +1 -0
  214. package/dist/providers/smb/smb.provider.d.ts +68 -0
  215. package/dist/providers/smb/smb.provider.d.ts.map +1 -0
  216. package/dist/providers/smb/smb.provider.js +382 -0
  217. package/dist/providers/smb/smb.provider.js.map +1 -0
  218. package/dist/server.d.ts +2 -0
  219. package/dist/server.d.ts.map +1 -0
  220. package/dist/server.js +44 -0
  221. package/dist/server.js.map +1 -0
  222. package/dist/services/audit/ad-audit.service.d.ts +70 -0
  223. package/dist/services/audit/ad-audit.service.d.ts.map +1 -0
  224. package/dist/services/audit/ad-audit.service.js +1019 -0
  225. package/dist/services/audit/ad-audit.service.js.map +1 -0
  226. package/dist/services/audit/attack-graph.service.d.ts +62 -0
  227. package/dist/services/audit/attack-graph.service.d.ts.map +1 -0
  228. package/dist/services/audit/attack-graph.service.js +702 -0
  229. package/dist/services/audit/attack-graph.service.js.map +1 -0
  230. package/dist/services/audit/audit.service.d.ts +4 -0
  231. package/dist/services/audit/audit.service.d.ts.map +1 -0
  232. package/dist/services/audit/audit.service.js +10 -0
  233. package/dist/services/audit/audit.service.js.map +1 -0
  234. package/dist/services/audit/azure-audit.service.d.ts +37 -0
  235. package/dist/services/audit/azure-audit.service.d.ts.map +1 -0
  236. package/dist/services/audit/azure-audit.service.js +153 -0
  237. package/dist/services/audit/azure-audit.service.js.map +1 -0
  238. package/dist/services/audit/detectors/ad/accounts.detector.d.ts +37 -0
  239. package/dist/services/audit/detectors/ad/accounts.detector.d.ts.map +1 -0
  240. package/dist/services/audit/detectors/ad/accounts.detector.js +881 -0
  241. package/dist/services/audit/detectors/ad/accounts.detector.js.map +1 -0
  242. package/dist/services/audit/detectors/ad/adcs.detector.d.ts +21 -0
  243. package/dist/services/audit/detectors/ad/adcs.detector.d.ts.map +1 -0
  244. package/dist/services/audit/detectors/ad/adcs.detector.js +227 -0
  245. package/dist/services/audit/detectors/ad/adcs.detector.js.map +1 -0
  246. package/dist/services/audit/detectors/ad/advanced.detector.d.ts +63 -0
  247. package/dist/services/audit/detectors/ad/advanced.detector.d.ts.map +1 -0
  248. package/dist/services/audit/detectors/ad/advanced.detector.js +867 -0
  249. package/dist/services/audit/detectors/ad/advanced.detector.js.map +1 -0
  250. package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts +16 -0
  251. package/dist/services/audit/detectors/ad/attack-paths.detector.d.ts.map +1 -0
  252. package/dist/services/audit/detectors/ad/attack-paths.detector.js +369 -0
  253. package/dist/services/audit/detectors/ad/attack-paths.detector.js.map +1 -0
  254. package/dist/services/audit/detectors/ad/compliance.detector.d.ts +28 -0
  255. package/dist/services/audit/detectors/ad/compliance.detector.d.ts.map +1 -0
  256. package/dist/services/audit/detectors/ad/compliance.detector.js +896 -0
  257. package/dist/services/audit/detectors/ad/compliance.detector.js.map +1 -0
  258. package/dist/services/audit/detectors/ad/computers.detector.d.ts +30 -0
  259. package/dist/services/audit/detectors/ad/computers.detector.d.ts.map +1 -0
  260. package/dist/services/audit/detectors/ad/computers.detector.js +799 -0
  261. package/dist/services/audit/detectors/ad/computers.detector.js.map +1 -0
  262. package/dist/services/audit/detectors/ad/gpo.detector.d.ts +17 -0
  263. package/dist/services/audit/detectors/ad/gpo.detector.d.ts.map +1 -0
  264. package/dist/services/audit/detectors/ad/gpo.detector.js +257 -0
  265. package/dist/services/audit/detectors/ad/gpo.detector.js.map +1 -0
  266. package/dist/services/audit/detectors/ad/groups.detector.d.ts +19 -0
  267. package/dist/services/audit/detectors/ad/groups.detector.d.ts.map +1 -0
  268. package/dist/services/audit/detectors/ad/groups.detector.js +488 -0
  269. package/dist/services/audit/detectors/ad/groups.detector.js.map +1 -0
  270. package/dist/services/audit/detectors/ad/index.d.ts +15 -0
  271. package/dist/services/audit/detectors/ad/index.d.ts.map +1 -0
  272. package/dist/services/audit/detectors/ad/index.js +51 -0
  273. package/dist/services/audit/detectors/ad/index.js.map +1 -0
  274. package/dist/services/audit/detectors/ad/kerberos.detector.d.ts +17 -0
  275. package/dist/services/audit/detectors/ad/kerberos.detector.d.ts.map +1 -0
  276. package/dist/services/audit/detectors/ad/kerberos.detector.js +293 -0
  277. package/dist/services/audit/detectors/ad/kerberos.detector.js.map +1 -0
  278. package/dist/services/audit/detectors/ad/monitoring.detector.d.ts +23 -0
  279. package/dist/services/audit/detectors/ad/monitoring.detector.d.ts.map +1 -0
  280. package/dist/services/audit/detectors/ad/monitoring.detector.js +328 -0
  281. package/dist/services/audit/detectors/ad/monitoring.detector.js.map +1 -0
  282. package/dist/services/audit/detectors/ad/network.detector.d.ts +39 -0
  283. package/dist/services/audit/detectors/ad/network.detector.d.ts.map +1 -0
  284. package/dist/services/audit/detectors/ad/network.detector.js +257 -0
  285. package/dist/services/audit/detectors/ad/network.detector.js.map +1 -0
  286. package/dist/services/audit/detectors/ad/password.detector.d.ts +14 -0
  287. package/dist/services/audit/detectors/ad/password.detector.d.ts.map +1 -0
  288. package/dist/services/audit/detectors/ad/password.detector.js +235 -0
  289. package/dist/services/audit/detectors/ad/password.detector.js.map +1 -0
  290. package/dist/services/audit/detectors/ad/permissions.detector.d.ts +20 -0
  291. package/dist/services/audit/detectors/ad/permissions.detector.d.ts.map +1 -0
  292. package/dist/services/audit/detectors/ad/permissions.detector.js +392 -0
  293. package/dist/services/audit/detectors/ad/permissions.detector.js.map +1 -0
  294. package/dist/services/audit/detectors/ad/trusts.detector.d.ts +11 -0
  295. package/dist/services/audit/detectors/ad/trusts.detector.d.ts.map +1 -0
  296. package/dist/services/audit/detectors/ad/trusts.detector.js +186 -0
  297. package/dist/services/audit/detectors/ad/trusts.detector.js.map +1 -0
  298. package/dist/services/audit/detectors/azure/app-security.detector.d.ts +11 -0
  299. package/dist/services/audit/detectors/azure/app-security.detector.d.ts.map +1 -0
  300. package/dist/services/audit/detectors/azure/app-security.detector.js +184 -0
  301. package/dist/services/audit/detectors/azure/app-security.detector.js.map +1 -0
  302. package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts +10 -0
  303. package/dist/services/audit/detectors/azure/conditional-access.detector.d.ts.map +1 -0
  304. package/dist/services/audit/detectors/azure/conditional-access.detector.js +130 -0
  305. package/dist/services/audit/detectors/azure/conditional-access.detector.js.map +1 -0
  306. package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts +8 -0
  307. package/dist/services/audit/detectors/azure/privilege-security.detector.d.ts.map +1 -0
  308. package/dist/services/audit/detectors/azure/privilege-security.detector.js +113 -0
  309. package/dist/services/audit/detectors/azure/privilege-security.detector.js.map +1 -0
  310. package/dist/services/audit/detectors/azure/user-security.detector.d.ts +14 -0
  311. package/dist/services/audit/detectors/azure/user-security.detector.d.ts.map +1 -0
  312. package/dist/services/audit/detectors/azure/user-security.detector.js +198 -0
  313. package/dist/services/audit/detectors/azure/user-security.detector.js.map +1 -0
  314. package/dist/services/audit/detectors/index.d.ts +2 -0
  315. package/dist/services/audit/detectors/index.d.ts.map +1 -0
  316. package/dist/services/audit/detectors/index.js +38 -0
  317. package/dist/services/audit/detectors/index.js.map +1 -0
  318. package/dist/services/audit/response-formatter.d.ts +176 -0
  319. package/dist/services/audit/response-formatter.d.ts.map +1 -0
  320. package/dist/services/audit/response-formatter.js +240 -0
  321. package/dist/services/audit/response-formatter.js.map +1 -0
  322. package/dist/services/audit/scoring.service.d.ts +15 -0
  323. package/dist/services/audit/scoring.service.d.ts.map +1 -0
  324. package/dist/services/audit/scoring.service.js +139 -0
  325. package/dist/services/audit/scoring.service.js.map +1 -0
  326. package/dist/services/auth/crypto.service.d.ts +19 -0
  327. package/dist/services/auth/crypto.service.d.ts.map +1 -0
  328. package/dist/services/auth/crypto.service.js +135 -0
  329. package/dist/services/auth/crypto.service.js.map +1 -0
  330. package/dist/services/auth/errors.d.ts +19 -0
  331. package/dist/services/auth/errors.d.ts.map +1 -0
  332. package/dist/services/auth/errors.js +46 -0
  333. package/dist/services/auth/errors.js.map +1 -0
  334. package/dist/services/auth/token.service.d.ts +41 -0
  335. package/dist/services/auth/token.service.d.ts.map +1 -0
  336. package/dist/services/auth/token.service.js +208 -0
  337. package/dist/services/auth/token.service.js.map +1 -0
  338. package/dist/services/config/config.service.d.ts +6 -0
  339. package/dist/services/config/config.service.d.ts.map +1 -0
  340. package/dist/services/config/config.service.js +64 -0
  341. package/dist/services/config/config.service.js.map +1 -0
  342. package/dist/services/export/export.service.d.ts +28 -0
  343. package/dist/services/export/export.service.d.ts.map +1 -0
  344. package/dist/services/export/export.service.js +28 -0
  345. package/dist/services/export/export.service.js.map +1 -0
  346. package/dist/services/export/formatters/csv.formatter.d.ts +8 -0
  347. package/dist/services/export/formatters/csv.formatter.d.ts.map +1 -0
  348. package/dist/services/export/formatters/csv.formatter.js +46 -0
  349. package/dist/services/export/formatters/csv.formatter.js.map +1 -0
  350. package/dist/services/export/formatters/json.formatter.d.ts +40 -0
  351. package/dist/services/export/formatters/json.formatter.d.ts.map +1 -0
  352. package/dist/services/export/formatters/json.formatter.js +58 -0
  353. package/dist/services/export/formatters/json.formatter.js.map +1 -0
  354. package/dist/services/jobs/azure-job-runner.d.ts +38 -0
  355. package/dist/services/jobs/azure-job-runner.d.ts.map +1 -0
  356. package/dist/services/jobs/azure-job-runner.js +199 -0
  357. package/dist/services/jobs/azure-job-runner.js.map +1 -0
  358. package/dist/services/jobs/index.d.ts +4 -0
  359. package/dist/services/jobs/index.d.ts.map +1 -0
  360. package/dist/services/jobs/index.js +20 -0
  361. package/dist/services/jobs/index.js.map +1 -0
  362. package/dist/services/jobs/job-runner.d.ts +64 -0
  363. package/dist/services/jobs/job-runner.d.ts.map +1 -0
  364. package/dist/services/jobs/job-runner.js +952 -0
  365. package/dist/services/jobs/job-runner.js.map +1 -0
  366. package/dist/services/jobs/job-store.d.ts +27 -0
  367. package/dist/services/jobs/job-store.d.ts.map +1 -0
  368. package/dist/services/jobs/job-store.js +261 -0
  369. package/dist/services/jobs/job-store.js.map +1 -0
  370. package/dist/services/jobs/job.types.d.ts +67 -0
  371. package/dist/services/jobs/job.types.d.ts.map +1 -0
  372. package/dist/services/jobs/job.types.js +36 -0
  373. package/dist/services/jobs/job.types.js.map +1 -0
  374. package/dist/types/ad.types.d.ts +74 -0
  375. package/dist/types/ad.types.d.ts.map +1 -0
  376. package/dist/types/ad.types.js +3 -0
  377. package/dist/types/ad.types.js.map +1 -0
  378. package/dist/types/adcs.types.d.ts +58 -0
  379. package/dist/types/adcs.types.d.ts.map +1 -0
  380. package/dist/types/adcs.types.js +38 -0
  381. package/dist/types/adcs.types.js.map +1 -0
  382. package/dist/types/attack-graph.types.d.ts +135 -0
  383. package/dist/types/attack-graph.types.d.ts.map +1 -0
  384. package/dist/types/attack-graph.types.js +58 -0
  385. package/dist/types/attack-graph.types.js.map +1 -0
  386. package/dist/types/audit.types.d.ts +34 -0
  387. package/dist/types/audit.types.d.ts.map +1 -0
  388. package/dist/types/audit.types.js +3 -0
  389. package/dist/types/audit.types.js.map +1 -0
  390. package/dist/types/azure.types.d.ts +61 -0
  391. package/dist/types/azure.types.d.ts.map +1 -0
  392. package/dist/types/azure.types.js +3 -0
  393. package/dist/types/azure.types.js.map +1 -0
  394. package/dist/types/config.types.d.ts +63 -0
  395. package/dist/types/config.types.d.ts.map +1 -0
  396. package/dist/types/config.types.js +3 -0
  397. package/dist/types/config.types.js.map +1 -0
  398. package/dist/types/error.types.d.ts +33 -0
  399. package/dist/types/error.types.d.ts.map +1 -0
  400. package/dist/types/error.types.js +70 -0
  401. package/dist/types/error.types.js.map +1 -0
  402. package/dist/types/finding.types.d.ts +133 -0
  403. package/dist/types/finding.types.d.ts.map +1 -0
  404. package/dist/types/finding.types.js +3 -0
  405. package/dist/types/finding.types.js.map +1 -0
  406. package/dist/types/gpo.types.d.ts +39 -0
  407. package/dist/types/gpo.types.d.ts.map +1 -0
  408. package/dist/types/gpo.types.js +15 -0
  409. package/dist/types/gpo.types.js.map +1 -0
  410. package/dist/types/token.types.d.ts +26 -0
  411. package/dist/types/token.types.d.ts.map +1 -0
  412. package/dist/types/token.types.js +3 -0
  413. package/dist/types/token.types.js.map +1 -0
  414. package/dist/types/trust.types.d.ts +45 -0
  415. package/dist/types/trust.types.d.ts.map +1 -0
  416. package/dist/types/trust.types.js +71 -0
  417. package/dist/types/trust.types.js.map +1 -0
  418. package/dist/utils/entity-converter.d.ts +17 -0
  419. package/dist/utils/entity-converter.d.ts.map +1 -0
  420. package/dist/utils/entity-converter.js +285 -0
  421. package/dist/utils/entity-converter.js.map +1 -0
  422. package/dist/utils/graph.util.d.ts +66 -0
  423. package/dist/utils/graph.util.d.ts.map +1 -0
  424. package/dist/utils/graph.util.js +382 -0
  425. package/dist/utils/graph.util.js.map +1 -0
  426. package/dist/utils/logger.d.ts +7 -0
  427. package/dist/utils/logger.d.ts.map +1 -0
  428. package/dist/utils/logger.js +86 -0
  429. package/dist/utils/logger.js.map +1 -0
  430. package/dist/utils/type-name-normalizer.d.ts +5 -0
  431. package/dist/utils/type-name-normalizer.d.ts.map +1 -0
  432. package/dist/utils/type-name-normalizer.js +218 -0
  433. package/dist/utils/type-name-normalizer.js.map +1 -0
  434. package/docker-compose.yml +26 -0
  435. package/docs/api/README.md +178 -0
  436. package/docs/api/openapi.yaml +1524 -0
  437. package/eslint.config.js +54 -0
  438. package/jest.config.js +38 -0
  439. package/package.json +97 -0
  440. package/scripts/fetch-ad-cert.sh +142 -0
  441. package/src/.gitkeep +0 -0
  442. package/src/api/.gitkeep +0 -0
  443. package/src/api/controllers/.gitkeep +0 -0
  444. package/src/api/controllers/audit.controller.ts +313 -0
  445. package/src/api/controllers/auth.controller.ts +258 -0
  446. package/src/api/controllers/export.controller.ts +153 -0
  447. package/src/api/controllers/health.controller.ts +16 -0
  448. package/src/api/controllers/jobs.controller.ts +187 -0
  449. package/src/api/controllers/providers.controller.ts +165 -0
  450. package/src/api/dto/.gitkeep +0 -0
  451. package/src/api/dto/AuditRequest.dto.ts +8 -0
  452. package/src/api/dto/AuditResponse.dto.ts +19 -0
  453. package/src/api/dto/TokenRequest.dto.ts +8 -0
  454. package/src/api/dto/TokenResponse.dto.ts +14 -0
  455. package/src/api/middlewares/.gitkeep +0 -0
  456. package/src/api/middlewares/authenticate.ts +203 -0
  457. package/src/api/middlewares/errorHandler.ts +54 -0
  458. package/src/api/middlewares/rateLimit.ts +35 -0
  459. package/src/api/middlewares/validate.ts +32 -0
  460. package/src/api/routes/.gitkeep +0 -0
  461. package/src/api/routes/audit.routes.ts +77 -0
  462. package/src/api/routes/auth.routes.ts +71 -0
  463. package/src/api/routes/export.routes.ts +34 -0
  464. package/src/api/routes/health.routes.ts +14 -0
  465. package/src/api/routes/index.ts +40 -0
  466. package/src/api/routes/providers.routes.ts +24 -0
  467. package/src/api/validators/.gitkeep +0 -0
  468. package/src/api/validators/audit.schemas.ts +59 -0
  469. package/src/api/validators/auth.schemas.ts +59 -0
  470. package/src/app.ts +87 -0
  471. package/src/config/.gitkeep +0 -0
  472. package/src/config/config.schema.ts +108 -0
  473. package/src/config/index.ts +82 -0
  474. package/src/container.ts +221 -0
  475. package/src/data/.gitkeep +0 -0
  476. package/src/data/database.ts +78 -0
  477. package/src/data/jobs/token-cleanup.job.ts +166 -0
  478. package/src/data/migrations/.gitkeep +0 -0
  479. package/src/data/migrations/001_initial_schema.sql +47 -0
  480. package/src/data/migrations/migration.runner.ts +125 -0
  481. package/src/data/models/.gitkeep +0 -0
  482. package/src/data/models/Token.model.ts +35 -0
  483. package/src/data/repositories/.gitkeep +0 -0
  484. package/src/data/repositories/token.repository.ts +160 -0
  485. package/src/providers/.gitkeep +0 -0
  486. package/src/providers/azure/.gitkeep +0 -0
  487. package/src/providers/azure/auth.provider.ts +14 -0
  488. package/src/providers/azure/azure-errors.ts +189 -0
  489. package/src/providers/azure/azure-retry.ts +168 -0
  490. package/src/providers/azure/graph-client.ts +315 -0
  491. package/src/providers/azure/graph.provider.ts +294 -0
  492. package/src/providers/azure/queries/app.queries.ts +9 -0
  493. package/src/providers/azure/queries/policy.queries.ts +9 -0
  494. package/src/providers/azure/queries/user.queries.ts +10 -0
  495. package/src/providers/interfaces/.gitkeep +0 -0
  496. package/src/providers/interfaces/IGraphProvider.ts +117 -0
  497. package/src/providers/interfaces/ILDAPProvider.ts +142 -0
  498. package/src/providers/ldap/.gitkeep +0 -0
  499. package/src/providers/ldap/acl-parser.ts +231 -0
  500. package/src/providers/ldap/ad-mappers.ts +280 -0
  501. package/src/providers/ldap/ldap-client.ts +259 -0
  502. package/src/providers/ldap/ldap-errors.ts +188 -0
  503. package/src/providers/ldap/ldap-retry.ts +267 -0
  504. package/src/providers/ldap/ldap-sanitizer.ts +273 -0
  505. package/src/providers/ldap/ldap.provider.ts +293 -0
  506. package/src/providers/ldap/queries/computer.queries.ts +9 -0
  507. package/src/providers/ldap/queries/group.queries.ts +9 -0
  508. package/src/providers/ldap/queries/user.queries.ts +10 -0
  509. package/src/providers/smb/smb.provider.ts +653 -0
  510. package/src/server.ts +60 -0
  511. package/src/services/.gitkeep +0 -0
  512. package/src/services/audit/.gitkeep +0 -0
  513. package/src/services/audit/ad-audit.service.ts +1481 -0
  514. package/src/services/audit/attack-graph.service.ts +1104 -0
  515. package/src/services/audit/audit.service.ts +12 -0
  516. package/src/services/audit/azure-audit.service.ts +286 -0
  517. package/src/services/audit/detectors/ad/accounts.detector.ts +1232 -0
  518. package/src/services/audit/detectors/ad/adcs.detector.ts +449 -0
  519. package/src/services/audit/detectors/ad/advanced.detector.ts +1270 -0
  520. package/src/services/audit/detectors/ad/attack-paths.detector.ts +600 -0
  521. package/src/services/audit/detectors/ad/compliance.detector.ts +1421 -0
  522. package/src/services/audit/detectors/ad/computers.detector.ts +1188 -0
  523. package/src/services/audit/detectors/ad/gpo.detector.ts +485 -0
  524. package/src/services/audit/detectors/ad/groups.detector.ts +685 -0
  525. package/src/services/audit/detectors/ad/index.ts +84 -0
  526. package/src/services/audit/detectors/ad/kerberos.detector.ts +424 -0
  527. package/src/services/audit/detectors/ad/monitoring.detector.ts +501 -0
  528. package/src/services/audit/detectors/ad/network.detector.ts +538 -0
  529. package/src/services/audit/detectors/ad/password.detector.ts +324 -0
  530. package/src/services/audit/detectors/ad/permissions.detector.ts +637 -0
  531. package/src/services/audit/detectors/ad/trusts.detector.ts +315 -0
  532. package/src/services/audit/detectors/azure/app-security.detector.ts +246 -0
  533. package/src/services/audit/detectors/azure/conditional-access.detector.ts +186 -0
  534. package/src/services/audit/detectors/azure/privilege-security.detector.ts +176 -0
  535. package/src/services/audit/detectors/azure/user-security.detector.ts +280 -0
  536. package/src/services/audit/detectors/index.ts +18 -0
  537. package/src/services/audit/response-formatter.ts +604 -0
  538. package/src/services/audit/scoring.service.ts +234 -0
  539. package/src/services/auth/.gitkeep +0 -0
  540. package/src/services/auth/crypto.service.ts +230 -0
  541. package/src/services/auth/errors.ts +47 -0
  542. package/src/services/auth/token.service.ts +420 -0
  543. package/src/services/config/.gitkeep +0 -0
  544. package/src/services/config/config.service.ts +75 -0
  545. package/src/services/export/.gitkeep +0 -0
  546. package/src/services/export/export.service.ts +99 -0
  547. package/src/services/export/formatters/csv.formatter.ts +124 -0
  548. package/src/services/export/formatters/json.formatter.ts +160 -0
  549. package/src/services/jobs/azure-job-runner.ts +312 -0
  550. package/src/services/jobs/index.ts +9 -0
  551. package/src/services/jobs/job-runner.ts +1280 -0
  552. package/src/services/jobs/job-store.ts +384 -0
  553. package/src/services/jobs/job.types.ts +182 -0
  554. package/src/types/.gitkeep +0 -0
  555. package/src/types/ad.types.ts +91 -0
  556. package/src/types/adcs.types.ts +107 -0
  557. package/src/types/attack-graph.types.ts +260 -0
  558. package/src/types/audit.types.ts +42 -0
  559. package/src/types/azure.types.ts +68 -0
  560. package/src/types/config.types.ts +79 -0
  561. package/src/types/error.types.ts +69 -0
  562. package/src/types/finding.types.ts +284 -0
  563. package/src/types/gpo.types.ts +72 -0
  564. package/src/types/smb2.d.ts +73 -0
  565. package/src/types/token.types.ts +32 -0
  566. package/src/types/trust.types.ts +140 -0
  567. package/src/utils/.gitkeep +0 -0
  568. package/src/utils/entity-converter.ts +453 -0
  569. package/src/utils/graph.util.ts +609 -0
  570. package/src/utils/logger.ts +111 -0
  571. package/src/utils/type-name-normalizer.ts +302 -0
  572. package/tests/.gitkeep +0 -0
  573. package/tests/e2e/.gitkeep +0 -0
  574. package/tests/fixtures/.gitkeep +0 -0
  575. package/tests/integration/.gitkeep +0 -0
  576. package/tests/integration/README.md +156 -0
  577. package/tests/integration/ad-audit.integration.test.ts +216 -0
  578. package/tests/integration/api/.gitkeep +0 -0
  579. package/tests/integration/api/endpoints.integration.test.ts +431 -0
  580. package/tests/integration/auth/jwt-authentication.integration.test.ts +358 -0
  581. package/tests/integration/providers/.gitkeep +0 -0
  582. package/tests/integration/providers/azure-basic.integration.test.ts +167 -0
  583. package/tests/integration/providers/ldap-basic.integration.test.ts +152 -0
  584. package/tests/integration/providers/ldap-connectivity.test.ts +44 -0
  585. package/tests/integration/providers/ldap-provider.integration.test.ts +347 -0
  586. package/tests/mocks/.gitkeep +0 -0
  587. package/tests/setup.ts +16 -0
  588. package/tests/unit/.gitkeep +0 -0
  589. package/tests/unit/api/middlewares/authenticate.test.ts +446 -0
  590. package/tests/unit/providers/.gitkeep +0 -0
  591. package/tests/unit/providers/azure/azure-errors.test.ts +193 -0
  592. package/tests/unit/providers/azure/azure-retry.test.ts +254 -0
  593. package/tests/unit/providers/azure/graph-provider.test.ts +313 -0
  594. package/tests/unit/providers/ldap/ad-mappers.test.ts +392 -0
  595. package/tests/unit/providers/ldap/ldap-provider.test.ts +376 -0
  596. package/tests/unit/providers/ldap/ldap-retry.test.ts +377 -0
  597. package/tests/unit/providers/ldap/ldap-sanitizer.test.ts +301 -0
  598. package/tests/unit/sample.test.ts +19 -0
  599. package/tests/unit/services/.gitkeep +0 -0
  600. package/tests/unit/services/audit/detectors/ad/accounts.detector.test.ts +393 -0
  601. package/tests/unit/services/audit/detectors/ad/advanced.detector.test.ts +380 -0
  602. package/tests/unit/services/audit/detectors/ad/computers.detector.test.ts +440 -0
  603. package/tests/unit/services/audit/detectors/ad/groups.detector.test.ts +276 -0
  604. package/tests/unit/services/audit/detectors/ad/kerberos.detector.test.ts +215 -0
  605. package/tests/unit/services/audit/detectors/ad/password.detector.test.ts +226 -0
  606. package/tests/unit/services/audit/detectors/ad/permissions.detector.test.ts +244 -0
  607. package/tests/unit/services/audit/detectors/azure/app-security.detector.test.ts +349 -0
  608. package/tests/unit/services/audit/detectors/azure/conditional-access.detector.test.ts +374 -0
  609. package/tests/unit/services/audit/detectors/azure/privilege-security.detector.test.ts +374 -0
  610. package/tests/unit/services/audit/detectors/azure/user-security.detector.test.ts +297 -0
  611. package/tests/unit/services/auth/crypto.service.test.ts +296 -0
  612. package/tests/unit/services/auth/token.service.test.ts +579 -0
  613. package/tests/unit/services/export/export.service.test.ts +241 -0
  614. package/tests/unit/services/export/formatters/csv.formatter.test.ts +270 -0
  615. package/tests/unit/services/export/formatters/json.formatter.test.ts +258 -0
  616. package/tests/unit/utils/.gitkeep +0 -0
  617. package/tsconfig.json +50 -0
@@ -0,0 +1,799 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectComputerConstrainedDelegation = detectComputerConstrainedDelegation;
4
+ exports.detectComputerRbcd = detectComputerRbcd;
5
+ exports.detectComputerInAdminGroup = detectComputerInAdminGroup;
6
+ exports.detectComputerDcsyncRights = detectComputerDcsyncRights;
7
+ exports.detectComputerUnconstrainedDelegation = detectComputerUnconstrainedDelegation;
8
+ exports.detectComputerStaleInactive = detectComputerStaleInactive;
9
+ exports.detectComputerPasswordOld = detectComputerPasswordOld;
10
+ exports.detectComputerWithSpns = detectComputerWithSpns;
11
+ exports.detectComputerNoLaps = detectComputerNoLaps;
12
+ exports.detectComputerAclAbuse = detectComputerAclAbuse;
13
+ exports.detectComputerDisabledNotDeleted = detectComputerDisabledNotDeleted;
14
+ exports.detectComputerWrongOu = detectComputerWrongOu;
15
+ exports.detectComputerWeakEncryption = detectComputerWeakEncryption;
16
+ exports.detectComputerDescriptionSensitive = detectComputerDescriptionSensitive;
17
+ exports.detectComputerPreWindows2000 = detectComputerPreWindows2000;
18
+ exports.detectComputerAdminCount = detectComputerAdminCount;
19
+ exports.detectComputerSmbSigningDisabled = detectComputerSmbSigningDisabled;
20
+ exports.detectComputerObsoleteOS = detectComputerObsoleteOS;
21
+ exports.detectComputerNeverLoggedOn = detectComputerNeverLoggedOn;
22
+ exports.detectComputerPreCreated = detectComputerPreCreated;
23
+ exports.detectDcNotInDcOu = detectDcNotInDcOu;
24
+ exports.detectComputerDuplicateSpn = detectComputerDuplicateSpn;
25
+ exports.detectServerNoAdminGroup = detectServerNoAdminGroup;
26
+ exports.detectWorkstationInServerOu = detectWorkstationInServerOu;
27
+ exports.detectComputerNoBitlocker = detectComputerNoBitlocker;
28
+ exports.detectComputerLegacyProtocol = detectComputerLegacyProtocol;
29
+ exports.detectComputersVulnerabilities = detectComputersVulnerabilities;
30
+ const entity_converter_1 = require("../../../../utils/entity-converter");
31
+ const FILETIME_EPOCH_OFFSET = 11644473600000;
32
+ function toTimestamp(value) {
33
+ if (!value)
34
+ return null;
35
+ if (value instanceof Date) {
36
+ const time = value.getTime();
37
+ return isNaN(time) ? null : time;
38
+ }
39
+ if (typeof value === 'string') {
40
+ if (value.includes('-') && value.includes('T')) {
41
+ const date = new Date(value);
42
+ const time = date.getTime();
43
+ return isNaN(time) ? null : time;
44
+ }
45
+ const gtMatch = value.match(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
46
+ if (gtMatch && gtMatch[1] && gtMatch[2] && gtMatch[3] && gtMatch[4] && gtMatch[5] && gtMatch[6]) {
47
+ const date = new Date(Date.UTC(parseInt(gtMatch[1], 10), parseInt(gtMatch[2], 10) - 1, parseInt(gtMatch[3], 10), parseInt(gtMatch[4], 10), parseInt(gtMatch[5], 10), parseInt(gtMatch[6], 10)));
48
+ const time = date.getTime();
49
+ return isNaN(time) ? null : time;
50
+ }
51
+ const parsed = parseInt(value, 10);
52
+ if (!isNaN(parsed) && parsed > 0) {
53
+ return filetimeToTimestamp(parsed);
54
+ }
55
+ return null;
56
+ }
57
+ if (typeof value === 'number') {
58
+ if (value <= 0)
59
+ return null;
60
+ if (value > 100000000000000) {
61
+ return filetimeToTimestamp(value);
62
+ }
63
+ if (value > 946684800000 && value < 4102444800000) {
64
+ return value;
65
+ }
66
+ if (value > 946684800 && value < 4102444800) {
67
+ return value * 1000;
68
+ }
69
+ return filetimeToTimestamp(value);
70
+ }
71
+ return null;
72
+ }
73
+ function filetimeToTimestamp(filetime) {
74
+ if (filetime === 0 || filetime >= Number.MAX_SAFE_INTEGER) {
75
+ return null;
76
+ }
77
+ const ms = filetime / 10000 - FILETIME_EPOCH_OFFSET;
78
+ if (ms < 0 || ms > 4102444800000) {
79
+ return null;
80
+ }
81
+ return ms;
82
+ }
83
+ function detectComputerConstrainedDelegation(computers, includeDetails) {
84
+ const affected = computers.filter((c) => {
85
+ const delegateTo = c['msDS-AllowedToDelegateTo'];
86
+ return delegateTo && (Array.isArray(delegateTo) ? delegateTo.length > 0 : delegateTo !== '');
87
+ });
88
+ return {
89
+ type: 'COMPUTER_CONSTRAINED_DELEGATION',
90
+ severity: 'critical',
91
+ category: 'computers',
92
+ title: 'Computer Constrained Delegation',
93
+ description: 'Computer with constrained Kerberos delegation. Can impersonate users to specified services.',
94
+ count: affected.length,
95
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
96
+ };
97
+ }
98
+ function detectComputerRbcd(computers, includeDetails) {
99
+ const affected = computers.filter((c) => {
100
+ const rbcdAttr = c['msDS-AllowedToActOnBehalfOfOtherIdentity'];
101
+ return rbcdAttr && (Array.isArray(rbcdAttr) ? rbcdAttr.length > 0 : rbcdAttr !== '');
102
+ });
103
+ return {
104
+ type: 'COMPUTER_RBCD',
105
+ severity: 'critical',
106
+ category: 'computers',
107
+ title: 'Computer RBCD',
108
+ description: 'Computer with Resource-Based Constrained Delegation. Enables privilege escalation via RBCD attack.',
109
+ count: affected.length,
110
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
111
+ };
112
+ }
113
+ function detectComputerInAdminGroup(computers, includeDetails) {
114
+ const adminGroups = ['Domain Admins', 'Enterprise Admins'];
115
+ const affected = computers.filter((c) => {
116
+ const memberOf = c.memberOf;
117
+ if (!memberOf)
118
+ return false;
119
+ return memberOf.some((dn) => adminGroups.some((group) => dn.includes(`CN=${group}`)));
120
+ });
121
+ return {
122
+ type: 'COMPUTER_IN_ADMIN_GROUP',
123
+ severity: 'critical',
124
+ category: 'computers',
125
+ title: 'Computer in Admin Group',
126
+ description: 'Computer account in Domain Admins or Enterprise Admins. Computer compromise leads to domain admin access.',
127
+ count: affected.length,
128
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
129
+ };
130
+ }
131
+ function detectComputerDcsyncRights(computers, includeDetails) {
132
+ const affected = computers.filter((c) => {
133
+ return 'replicationRights' in c && c.replicationRights;
134
+ });
135
+ return {
136
+ type: 'COMPUTER_DCSYNC_RIGHTS',
137
+ severity: 'critical',
138
+ category: 'computers',
139
+ title: 'Computer DCSync Rights',
140
+ description: 'Computer with DCSync replication rights. Can extract all domain password hashes.',
141
+ count: affected.length,
142
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
143
+ };
144
+ }
145
+ function detectComputerUnconstrainedDelegation(computers, includeDetails) {
146
+ const affected = computers.filter((c) => {
147
+ const uac = c.userAccountControl;
148
+ if (!uac)
149
+ return false;
150
+ return (uac & 0x80000) !== 0;
151
+ });
152
+ return {
153
+ type: 'COMPUTER_UNCONSTRAINED_DELEGATION',
154
+ severity: 'critical',
155
+ category: 'computers',
156
+ title: 'Computer Unconstrained Delegation',
157
+ description: 'Computer with unconstrained delegation enabled. Servers can be used for privilege escalation attacks.',
158
+ count: affected.length,
159
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
160
+ };
161
+ }
162
+ function detectComputerStaleInactive(computers, includeDetails) {
163
+ const now = Date.now();
164
+ const ninetyDaysAgo = now - 90 * 24 * 60 * 60 * 1000;
165
+ const affected = computers.filter((c) => {
166
+ if (!c.enabled)
167
+ return false;
168
+ const lastLogonTime = toTimestamp(c.lastLogon) ?? toTimestamp(c['lastLogonTimestamp']);
169
+ if (!lastLogonTime)
170
+ return false;
171
+ return lastLogonTime < ninetyDaysAgo;
172
+ });
173
+ return {
174
+ type: 'COMPUTER_STALE_INACTIVE',
175
+ severity: 'high',
176
+ category: 'computers',
177
+ title: 'Computer Stale/Inactive',
178
+ description: 'Computer inactive for 90+ days. Orphaned computer accounts could be exploited without detection.',
179
+ count: affected.length,
180
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
181
+ };
182
+ }
183
+ function detectComputerPasswordOld(computers, includeDetails) {
184
+ const now = Date.now();
185
+ const ninetyDaysAgo = now - 90 * 24 * 60 * 60 * 1000;
186
+ let debugStats = { total: 0, disabled: 0, noPwdLastSet: 0, recent: 0, old: 0 };
187
+ const affected = computers.filter((c) => {
188
+ debugStats.total++;
189
+ if (!c.enabled) {
190
+ debugStats.disabled++;
191
+ return false;
192
+ }
193
+ const pwdLastSet = toTimestamp(c.pwdLastSet) ?? toTimestamp(c.passwordLastSet);
194
+ if (!pwdLastSet) {
195
+ debugStats.noPwdLastSet++;
196
+ return false;
197
+ }
198
+ if (pwdLastSet < ninetyDaysAgo) {
199
+ debugStats.old++;
200
+ return true;
201
+ }
202
+ debugStats.recent++;
203
+ return false;
204
+ });
205
+ return {
206
+ type: 'COMPUTER_PASSWORD_OLD',
207
+ severity: 'high',
208
+ category: 'computers',
209
+ title: 'Computer Password Old',
210
+ description: 'Computer password not changed for 90+ days. Increases risk of password-based attacks.',
211
+ count: affected.length,
212
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
213
+ details: {
214
+ debug: debugStats,
215
+ threshold: '90 days',
216
+ checkDate: new Date(ninetyDaysAgo).toISOString(),
217
+ },
218
+ };
219
+ }
220
+ function detectComputerWithSpns(computers, includeDetails) {
221
+ const affected = computers.filter((c) => {
222
+ const spns = c.servicePrincipalName;
223
+ return spns && spns.length > 0;
224
+ });
225
+ return {
226
+ type: 'COMPUTER_WITH_SPNS',
227
+ severity: 'high',
228
+ category: 'computers',
229
+ title: 'Computer with SPNs',
230
+ description: 'Computer with Service Principal Names. Enables Kerberoasting attack against computer account.',
231
+ count: affected.length,
232
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
233
+ };
234
+ }
235
+ function detectComputerNoLaps(computers, includeDetails) {
236
+ const total = computers.length;
237
+ const disabled = computers.filter((c) => !c.enabled).length;
238
+ const enabled = total - disabled;
239
+ const domainControllers = computers.filter((c) => {
240
+ const uac = c.userAccountControl;
241
+ return uac && (uac & 0x2000) !== 0;
242
+ }).length;
243
+ let hasLegacyLapsSchema = false;
244
+ let hasWindowsLapsSchema = false;
245
+ let withLegacyLaps = 0;
246
+ let withWindowsLaps = 0;
247
+ const affected = computers.filter((c) => {
248
+ if (!c.enabled)
249
+ return false;
250
+ const uac = c.userAccountControl;
251
+ if (uac && (uac & 0x2000) !== 0)
252
+ return false;
253
+ const comp = c;
254
+ const legacyLaps = comp['ms-Mcs-AdmPwd'];
255
+ const legacyLapsExpiry = comp['ms-Mcs-AdmPwdExpirationTime'];
256
+ const isValidLapsValue = (val) => {
257
+ if (val === undefined || val === null || val === '')
258
+ return false;
259
+ if (Array.isArray(val) && val.length === 0)
260
+ return false;
261
+ if (val === '0' || val === 0)
262
+ return false;
263
+ return true;
264
+ };
265
+ if (isValidLapsValue(legacyLaps) || isValidLapsValue(legacyLapsExpiry)) {
266
+ hasLegacyLapsSchema = true;
267
+ }
268
+ const hasLegacyLaps = isValidLapsValue(legacyLaps) || isValidLapsValue(legacyLapsExpiry);
269
+ if (hasLegacyLaps)
270
+ withLegacyLaps++;
271
+ const windowsLaps = comp['msLAPS-Password'];
272
+ const windowsLapsExpiry = comp['msLAPS-PasswordExpirationTime'];
273
+ if (isValidLapsValue(windowsLaps) || isValidLapsValue(windowsLapsExpiry)) {
274
+ hasWindowsLapsSchema = true;
275
+ }
276
+ const hasWindowsLaps = isValidLapsValue(windowsLaps) || isValidLapsValue(windowsLapsExpiry);
277
+ if (hasWindowsLaps)
278
+ withWindowsLaps++;
279
+ return !hasLegacyLaps && !hasWindowsLaps;
280
+ });
281
+ const schemaExtended = hasLegacyLapsSchema || hasWindowsLapsSchema;
282
+ const eligibleComputers = enabled - domainControllers;
283
+ return {
284
+ type: 'COMPUTER_NO_LAPS',
285
+ severity: !schemaExtended ? 'critical' : 'high',
286
+ category: 'computers',
287
+ title: !schemaExtended ? 'LAPS Not Deployed (Schema Not Extended)' : 'Computer No LAPS',
288
+ description: !schemaExtended
289
+ ? 'LAPS schema is not extended in Active Directory. ALL local admin passwords are unmanaged and likely shared across computers.'
290
+ : 'Computer without LAPS deployed. Shared/static local admin passwords across workstations.',
291
+ count: affected.length,
292
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
293
+ details: {
294
+ debug: {
295
+ total,
296
+ enabled,
297
+ disabled,
298
+ domainControllers,
299
+ eligibleComputers,
300
+ withLegacyLaps,
301
+ withWindowsLaps,
302
+ withoutLaps: affected.length,
303
+ schemaExtended,
304
+ hasLegacyLapsSchema,
305
+ hasWindowsLapsSchema,
306
+ },
307
+ recommendation: !schemaExtended
308
+ ? 'Install LAPS (legacy or Windows LAPS) and extend the AD schema. Then deploy via GPO.'
309
+ : 'Deploy LAPS to remaining computers via GPO.',
310
+ },
311
+ };
312
+ }
313
+ function detectComputerAclAbuse(computers, includeDetails) {
314
+ const affected = computers.filter((c) => {
315
+ return 'dangerousAcl' in c && c.dangerousAcl;
316
+ });
317
+ return {
318
+ type: 'COMPUTER_ACL_ABUSE',
319
+ severity: 'high',
320
+ category: 'computers',
321
+ title: 'Computer ACL Abuse',
322
+ description: 'Computer with dangerous ACL permissions. Can modify computer object properties and escalate privileges.',
323
+ count: affected.length,
324
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
325
+ };
326
+ }
327
+ function detectComputerDisabledNotDeleted(computers, includeDetails) {
328
+ const now = Date.now();
329
+ const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1000;
330
+ const debugStats = { total: 0, enabled: 0, noWhenChanged: 0, recent: 0, old: 0, sampleDates: [] };
331
+ const affected = computers.filter((c) => {
332
+ debugStats.total++;
333
+ if (c.enabled) {
334
+ debugStats.enabled++;
335
+ return false;
336
+ }
337
+ const rawWhenChanged = c.whenChanged;
338
+ const whenChangedTime = toTimestamp(rawWhenChanged);
339
+ if (debugStats.sampleDates.length < 5) {
340
+ debugStats.sampleDates.push({
341
+ name: c.sAMAccountName || 'unknown',
342
+ raw: rawWhenChanged,
343
+ rawType: typeof rawWhenChanged,
344
+ rawStringified: JSON.stringify(rawWhenChanged),
345
+ parsed: whenChangedTime,
346
+ asIso: whenChangedTime ? new Date(whenChangedTime).toISOString() : null,
347
+ whenCreated: c.whenCreated,
348
+ });
349
+ }
350
+ if (!whenChangedTime) {
351
+ debugStats.noWhenChanged++;
352
+ return false;
353
+ }
354
+ if (whenChangedTime < thirtyDaysAgo) {
355
+ debugStats.old++;
356
+ return true;
357
+ }
358
+ debugStats.recent++;
359
+ return false;
360
+ });
361
+ return {
362
+ type: 'COMPUTER_DISABLED_NOT_DELETED',
363
+ severity: 'medium',
364
+ category: 'computers',
365
+ title: 'Computer Disabled Not Deleted',
366
+ description: 'Disabled computer not deleted (>30 days). Clutters AD, potential security oversight.',
367
+ count: affected.length,
368
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
369
+ details: {
370
+ debug: debugStats,
371
+ threshold: '30 days',
372
+ checkDate: new Date(thirtyDaysAgo).toISOString(),
373
+ nowDate: new Date(now).toISOString(),
374
+ },
375
+ };
376
+ }
377
+ function detectComputerWrongOu(computers, includeDetails) {
378
+ const affected = computers.filter((c) => {
379
+ const dnLower = c.dn.toLowerCase();
380
+ const isInDefaultContainer = dnLower.includes(',cn=computers,dc=');
381
+ return isInDefaultContainer;
382
+ });
383
+ return {
384
+ type: 'COMPUTER_WRONG_OU',
385
+ severity: 'medium',
386
+ category: 'computers',
387
+ title: 'Computer in Default Container',
388
+ description: 'Computer in default Computers container instead of an organizational OU. ' +
389
+ 'May not receive proper Group Policy and indicates lack of organization.',
390
+ count: affected.length,
391
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
392
+ };
393
+ }
394
+ function detectComputerWeakEncryption(computers, includeDetails) {
395
+ const affected = computers.filter((c) => {
396
+ const encTypes = c['msDS-SupportedEncryptionTypes'];
397
+ if (typeof encTypes !== 'number')
398
+ return false;
399
+ return (encTypes & 0x18) === 0 && (encTypes & 0x7) !== 0;
400
+ });
401
+ return {
402
+ type: 'COMPUTER_WEAK_ENCRYPTION',
403
+ severity: 'medium',
404
+ category: 'computers',
405
+ title: 'Computer Weak Encryption',
406
+ description: 'Computer with weak encryption types (DES/RC4 only). Vulnerable to Kerberos downgrade attacks.',
407
+ count: affected.length,
408
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
409
+ };
410
+ }
411
+ function detectComputerDescriptionSensitive(computers, includeDetails) {
412
+ const sensitivePatterns = [
413
+ /password|passwd|pwd/i,
414
+ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/,
415
+ /admin|root|sa/i,
416
+ ];
417
+ const affected = computers.filter((c) => {
418
+ const rawDesc = c.description;
419
+ const description = (0, entity_converter_1.ldapAttrToString)(rawDesc);
420
+ if (!description)
421
+ return false;
422
+ return sensitivePatterns.some((pattern) => pattern.test(description));
423
+ });
424
+ return {
425
+ type: 'COMPUTER_DESCRIPTION_SENSITIVE',
426
+ severity: 'medium',
427
+ category: 'computers',
428
+ title: 'Computer Description Sensitive',
429
+ description: 'Computer description contains sensitive data (passwords, IPs, etc.). Information disclosure.',
430
+ count: affected.length,
431
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
432
+ };
433
+ }
434
+ function detectComputerPreWindows2000(computers, includeDetails) {
435
+ const affected = computers.filter((c) => {
436
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
437
+ if (!os)
438
+ return false;
439
+ return /Windows NT|Windows 2000|Windows 95|Windows 98/i.test(os);
440
+ });
441
+ return {
442
+ type: 'COMPUTER_PRE_WINDOWS_2000',
443
+ severity: 'medium',
444
+ category: 'computers',
445
+ title: 'Pre-Windows 2000 Computer',
446
+ description: 'Pre-Windows 2000 compatible computer. Weak security settings, potential compatibility exploits.',
447
+ count: affected.length,
448
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
449
+ };
450
+ }
451
+ function detectComputerAdminCount(computers, includeDetails) {
452
+ const affected = computers.filter((c) => {
453
+ const adminCount = c.adminCount;
454
+ return adminCount === 1;
455
+ });
456
+ return {
457
+ type: 'COMPUTER_ADMIN_COUNT',
458
+ severity: 'low',
459
+ category: 'computers',
460
+ title: 'Computer adminCount Set',
461
+ description: 'Computer with adminCount attribute set to 1. May indicate current or former administrative privileges.',
462
+ count: affected.length,
463
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
464
+ };
465
+ }
466
+ function detectComputerSmbSigningDisabled(computers, includeDetails) {
467
+ const affected = computers.filter((c) => {
468
+ return 'smbSigningDisabled' in c && c.smbSigningDisabled;
469
+ });
470
+ return {
471
+ type: 'COMPUTER_SMB_SIGNING_DISABLED',
472
+ severity: 'low',
473
+ category: 'computers',
474
+ title: 'Computer SMB Signing Disabled',
475
+ description: 'Computer with SMB signing disabled. Vulnerable to SMB relay attacks (informational finding).',
476
+ count: affected.length,
477
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
478
+ };
479
+ }
480
+ const OBSOLETE_OS_PATTERNS = [
481
+ {
482
+ pattern: /Windows XP/i,
483
+ type: 'COMPUTER_OS_OBSOLETE_XP',
484
+ severity: 'critical',
485
+ osName: 'Windows XP',
486
+ },
487
+ {
488
+ pattern: /Server 2003/i,
489
+ type: 'COMPUTER_OS_OBSOLETE_2003',
490
+ severity: 'critical',
491
+ osName: 'Windows Server 2003',
492
+ },
493
+ {
494
+ pattern: /Server 2008(?!\s*R2)/i,
495
+ type: 'COMPUTER_OS_OBSOLETE_2008',
496
+ severity: 'high',
497
+ osName: 'Windows Server 2008',
498
+ },
499
+ {
500
+ pattern: /Windows Vista/i,
501
+ type: 'COMPUTER_OS_OBSOLETE_VISTA',
502
+ severity: 'high',
503
+ osName: 'Windows Vista',
504
+ },
505
+ ];
506
+ function detectComputerObsoleteOS(computers, includeDetails) {
507
+ return OBSOLETE_OS_PATTERNS.map(({ pattern, type, severity, osName }) => {
508
+ const affected = computers.filter((c) => {
509
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
510
+ return os && pattern.test(os);
511
+ });
512
+ return {
513
+ type,
514
+ severity,
515
+ category: 'computers',
516
+ title: `Obsolete OS: ${osName}`,
517
+ description: `Computers running ${osName}, an unsupported operating system. No security patches available, making these systems highly vulnerable to exploitation.`,
518
+ count: affected.length,
519
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
520
+ };
521
+ }).filter((f) => f.count > 0);
522
+ }
523
+ function detectComputerNeverLoggedOn(computers, includeDetails) {
524
+ const affected = computers.filter((c) => {
525
+ if (!c.enabled)
526
+ return false;
527
+ const lastLogonTime = toTimestamp(c.lastLogon) ?? toTimestamp(c['lastLogonTimestamp']);
528
+ return !lastLogonTime;
529
+ });
530
+ return {
531
+ type: 'COMPUTER_NEVER_LOGGED_ON',
532
+ severity: 'medium',
533
+ category: 'computers',
534
+ title: 'Computer Never Logged On',
535
+ description: 'Enabled computer accounts that have never authenticated to the domain. These may be orphaned accounts from failed deployments or unused systems that should be cleaned up.',
536
+ count: affected.length,
537
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
538
+ };
539
+ }
540
+ function detectComputerPreCreated(computers, includeDetails) {
541
+ const affected = computers.filter((c) => {
542
+ if (c.enabled)
543
+ return false;
544
+ const lastLogonTime = toTimestamp(c.lastLogon) ?? toTimestamp(c['lastLogonTimestamp']);
545
+ return !lastLogonTime;
546
+ });
547
+ return {
548
+ type: 'COMPUTER_PRE_CREATED',
549
+ severity: 'medium',
550
+ category: 'computers',
551
+ title: 'Computer Pre-Created (Staging)',
552
+ description: 'Disabled computer accounts that have never logged on. These are staging accounts that were created but never deployed. Should be reviewed and cleaned up.',
553
+ count: affected.length,
554
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
555
+ };
556
+ }
557
+ function detectDcNotInDcOu(computers, includeDetails) {
558
+ const dcPatterns = [/^DC\d*/i, /domain controller/i];
559
+ const affected = computers.filter((c) => {
560
+ const dnsName = typeof c.dNSHostName === 'string' ? c.dNSHostName : (Array.isArray(c.dNSHostName) ? c.dNSHostName[0] : '');
561
+ const isDC = dcPatterns.some((p) => p.test(c.sAMAccountName || '')) ||
562
+ (dnsName && dnsName.toLowerCase().includes('dc')) ||
563
+ ((c.userAccountControl ?? 0) & 0x2000) !== 0;
564
+ if (!isDC)
565
+ return false;
566
+ const isInDCOU = c.dn.toLowerCase().includes('ou=domain controllers');
567
+ return !isInDCOU;
568
+ });
569
+ return {
570
+ type: 'DC_NOT_IN_DC_OU',
571
+ severity: 'high',
572
+ category: 'computers',
573
+ title: 'Domain Controller Not in Domain Controllers OU',
574
+ description: 'Domain Controllers found outside the Domain Controllers OU. This may indicate misconfiguration or an attempt to hide a rogue DC.',
575
+ count: affected.length,
576
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
577
+ details: affected.length > 0
578
+ ? {
579
+ recommendation: 'Move all Domain Controllers to the Domain Controllers OU for proper GPO application and management.',
580
+ risks: [
581
+ 'GPOs targeting Domain Controllers OU may not apply',
582
+ 'May indicate rogue or compromised DC',
583
+ 'Security baselines may not be applied correctly',
584
+ ],
585
+ }
586
+ : undefined,
587
+ };
588
+ }
589
+ function detectComputerDuplicateSpn(computers, includeDetails) {
590
+ const spnMap = new Map();
591
+ for (const computer of computers) {
592
+ const spns = computer['servicePrincipalName'];
593
+ if (!spns || !Array.isArray(spns))
594
+ continue;
595
+ for (const spn of spns) {
596
+ const normalizedSpn = spn.toLowerCase();
597
+ if (!spnMap.has(normalizedSpn)) {
598
+ spnMap.set(normalizedSpn, []);
599
+ }
600
+ spnMap.get(normalizedSpn).push(computer);
601
+ }
602
+ }
603
+ const duplicateComputers = new Set();
604
+ const duplicateSpns = [];
605
+ for (const [spn, computersList] of spnMap.entries()) {
606
+ if (computersList.length > 1) {
607
+ duplicateSpns.push({
608
+ spn,
609
+ computers: computersList.map((c) => c.sAMAccountName || c.dn),
610
+ });
611
+ computersList.forEach((c) => duplicateComputers.add(c));
612
+ }
613
+ }
614
+ return {
615
+ type: 'COMPUTER_DUPLICATE_SPN',
616
+ severity: 'medium',
617
+ category: 'computers',
618
+ title: 'Duplicate SPNs Detected',
619
+ description: 'Multiple computers share the same Service Principal Name. This causes Kerberos authentication failures.',
620
+ count: duplicateComputers.size,
621
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(Array.from(duplicateComputers)) : undefined,
622
+ details: duplicateSpns.length > 0
623
+ ? {
624
+ duplicateSpns: duplicateSpns.slice(0, 10),
625
+ totalDuplicates: duplicateSpns.length,
626
+ recommendation: 'Remove duplicate SPNs using setspn -D. Ensure each SPN is unique across the domain.',
627
+ }
628
+ : undefined,
629
+ };
630
+ }
631
+ function detectServerNoAdminGroup(computers, includeDetails) {
632
+ const serverPatterns = [/server/i, /^srv/i, /^sql/i, /^web/i, /^app/i, /^db/i, /^file/i];
633
+ const serverOsPatterns = [/server/i];
634
+ const affected = computers.filter((c) => {
635
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
636
+ const isServer = serverPatterns.some((p) => p.test(c.sAMAccountName || '')) ||
637
+ (os && serverOsPatterns.some((p) => p.test(os)));
638
+ if (!isServer)
639
+ return false;
640
+ if (!c.enabled)
641
+ return false;
642
+ const rawDesc = c['description'];
643
+ const description = (typeof rawDesc === 'string' ? rawDesc : (Array.isArray(rawDesc) ? rawDesc[0] : '') || '').toLowerCase();
644
+ const isUnmanaged = description.includes('unmanaged') ||
645
+ description.includes('legacy') ||
646
+ description.includes('deprecated');
647
+ return isUnmanaged;
648
+ });
649
+ return {
650
+ type: 'SERVER_NO_ADMIN_GROUP',
651
+ severity: 'medium',
652
+ category: 'computers',
653
+ title: 'Server Without Managed Admin Group',
654
+ description: 'Servers identified as unmanaged or without proper administrative group documentation. Local admin access may not be properly controlled.',
655
+ count: affected.length,
656
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
657
+ details: affected.length > 0
658
+ ? {
659
+ recommendation: 'Create dedicated admin groups for each server (e.g., SRV01-Admins) and document access.',
660
+ risks: [
661
+ 'Unknown administrators may have access',
662
+ 'Audit trail for admin actions may be incomplete',
663
+ 'Compliance violations for access management',
664
+ ],
665
+ }
666
+ : undefined,
667
+ };
668
+ }
669
+ function detectWorkstationInServerOu(computers, includeDetails) {
670
+ const serverOuPatterns = [/ou=servers/i, /ou=server/i, /ou=datacenter/i, /ou=production/i];
671
+ const workstationOsPatterns = [/windows 10/i, /windows 11/i, /windows 7/i, /windows 8/i];
672
+ const workstationNamePatterns = [/^ws/i, /^pc/i, /^laptop/i, /^desktop/i, /^nb/i];
673
+ const affected = computers.filter((c) => {
674
+ const isInServerOU = serverOuPatterns.some((p) => p.test(c.dn));
675
+ if (!isInServerOU)
676
+ return false;
677
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
678
+ const isWorkstation = workstationNamePatterns.some((p) => p.test(c.sAMAccountName || '')) ||
679
+ (os && workstationOsPatterns.some((p) => p.test(os)));
680
+ return isWorkstation;
681
+ });
682
+ return {
683
+ type: 'WORKSTATION_IN_SERVER_OU',
684
+ severity: 'low',
685
+ category: 'computers',
686
+ title: 'Workstation in Server OU',
687
+ description: 'Workstation computers found in server OUs. This causes incorrect GPO application and may indicate organizational issues.',
688
+ count: affected.length,
689
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
690
+ details: affected.length > 0
691
+ ? {
692
+ recommendation: 'Move workstations to appropriate workstation OUs for proper GPO targeting.',
693
+ impact: 'Server-targeted GPOs may apply to workstations causing configuration issues.',
694
+ }
695
+ : undefined,
696
+ };
697
+ }
698
+ function detectComputerNoBitlocker(computers, includeDetails) {
699
+ const serversWithoutBitlocker = computers.filter((c) => {
700
+ if (!c.enabled)
701
+ return false;
702
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem).toLowerCase();
703
+ const isServer = os.includes('server');
704
+ const hasBitlockerInfo = c['ms-FVE-RecoveryInformation'] !== undefined;
705
+ return isServer && !hasBitlockerInfo;
706
+ });
707
+ return {
708
+ type: 'COMPUTER_NO_BITLOCKER',
709
+ severity: 'high',
710
+ category: 'computers',
711
+ title: 'BitLocker Not Detected',
712
+ description: 'Servers without BitLocker recovery information in AD. ' +
713
+ 'Unencrypted disks are vulnerable to physical theft and offline attacks.',
714
+ count: serversWithoutBitlocker.length,
715
+ affectedEntities: includeDetails
716
+ ? (0, entity_converter_1.toAffectedComputerEntities)(serversWithoutBitlocker)
717
+ : undefined,
718
+ details: {
719
+ recommendation: 'Enable BitLocker on all servers and configure AD backup of recovery keys.',
720
+ note: 'This detection checks for ms-FVE-RecoveryInformation in AD. Standalone BitLocker may not be detected.',
721
+ },
722
+ };
723
+ }
724
+ function detectComputerLegacyProtocol(computers, includeDetails) {
725
+ const legacyOsPatterns = [
726
+ /Windows XP/i,
727
+ /Windows 2000/i,
728
+ /Windows NT/i,
729
+ /Server 2003/i,
730
+ /Windows Vista/i,
731
+ ];
732
+ const affected = computers.filter((c) => {
733
+ if (!c.enabled)
734
+ return false;
735
+ const os = (0, entity_converter_1.ldapAttrToString)(c.operatingSystem);
736
+ const hasLegacyOs = legacyOsPatterns.some((p) => p.test(os));
737
+ if (hasLegacyOs)
738
+ return true;
739
+ const encTypes = c['msDS-SupportedEncryptionTypes'];
740
+ if (encTypes !== undefined) {
741
+ const onlyLegacy = (encTypes & 0x18) === 0;
742
+ if (onlyLegacy && encTypes > 0)
743
+ return true;
744
+ }
745
+ return false;
746
+ });
747
+ return {
748
+ type: 'COMPUTER_LEGACY_PROTOCOL',
749
+ severity: 'medium',
750
+ category: 'computers',
751
+ title: 'Legacy Protocol Support',
752
+ description: 'Computers configured to use legacy protocols (SMBv1, NTLMv1, DES/RC4 only). ' +
753
+ 'These are vulnerable to relay attacks, credential theft, and encryption downgrade.',
754
+ count: affected.length,
755
+ affectedEntities: includeDetails ? (0, entity_converter_1.toAffectedComputerEntities)(affected) : undefined,
756
+ details: {
757
+ recommendation: 'Upgrade legacy systems or disable legacy protocols. Enable AES encryption support.',
758
+ protocols: ['SMBv1', 'NTLMv1', 'DES', 'RC4'],
759
+ },
760
+ };
761
+ }
762
+ function detectComputersVulnerabilities(computers, includeDetails) {
763
+ const obsoleteOsFindings = detectComputerObsoleteOS(computers, includeDetails);
764
+ return [
765
+ ...obsoleteOsFindings,
766
+ detectComputerNeverLoggedOn(computers, includeDetails),
767
+ detectComputerPreCreated(computers, includeDetails),
768
+ detectComputerConstrainedDelegation(computers, includeDetails),
769
+ detectComputerRbcd(computers, includeDetails),
770
+ detectComputerInAdminGroup(computers, includeDetails),
771
+ detectComputerDcsyncRights(computers, includeDetails),
772
+ detectComputerUnconstrainedDelegation(computers, includeDetails),
773
+ detectComputerStaleInactive(computers, includeDetails),
774
+ detectComputerPasswordOld(computers, includeDetails),
775
+ detectComputerWithSpns(computers, includeDetails),
776
+ detectComputerNoLaps(computers, includeDetails),
777
+ detectComputerAclAbuse(computers, includeDetails),
778
+ detectComputerDisabledNotDeleted(computers, includeDetails),
779
+ detectComputerWrongOu(computers, includeDetails),
780
+ detectComputerWeakEncryption(computers, includeDetails),
781
+ detectComputerDescriptionSensitive(computers, includeDetails),
782
+ detectComputerPreWindows2000(computers, includeDetails),
783
+ detectComputerAdminCount(computers, includeDetails),
784
+ detectComputerSmbSigningDisabled(computers, includeDetails),
785
+ detectDcNotInDcOu(computers, includeDetails),
786
+ detectComputerDuplicateSpn(computers, includeDetails),
787
+ detectServerNoAdminGroup(computers, includeDetails),
788
+ detectWorkstationInServerOu(computers, includeDetails),
789
+ detectComputerNoBitlocker(computers, includeDetails),
790
+ detectComputerLegacyProtocol(computers, includeDetails),
791
+ ].filter((finding) => {
792
+ if (finding.count > 0)
793
+ return true;
794
+ if (finding.details?.['debug'])
795
+ return true;
796
+ return false;
797
+ });
798
+ }
799
+ //# sourceMappingURL=computers.detector.js.map