
Escanea volcados de dominio de Azure exportados en busca de contraseñas en texto plano, cadenas de conexión, claves de almacenamiento y otros secretos; genera informes CSV/HTML redactados para flujos de trabajo de auditoría de solo lectura.
Un escáner de PowerShell que examina la salida de Get-AzDomainInfo de MicroBurst en busca de contraseñas en texto plano, claves, cadenas de conexión y otros secretos que nunca deberían permanecer sin cifrar en un entorno de Azure.
Diseñado para flujos de trabajo de auditoría de solo lectura: recopilas un volcado de dominio con MicroBurst (el acceso de Lector es suficiente para Get-AzDomainInfo) y luego apuntas esta herramienta a la carpeta de salida. No toca Azure en sí; solo lee los archivos que ya exportaste. Los valores de secretos están redactados en todos los informes, por lo que la salida se puede adjuntar de forma segura a los hallazgos.
# Clone / copy this folder, then from a PowerShell prompt:
.\Scan-MicroBurst.ps1 -Path .\MicroBurst-2026 -Verbose
O importa el módulo y usa el cmdlet directamente:
Import-Module .\MicroBurstSecretsHunter.psd1 -Force
Invoke-MBSecretScan -Path .\MicroBurst-2026
Los informes se escriben en una carpeta con marca de tiempo (MBSecretScan-<timestamp>) en el directorio actual, a menos que pases -OutputDirectory.
De forma predeterminada, cada valor está redactado, por lo que los informes son seguros de compartir. Los caracteres revelados se limitan a una cuarta parte de la longitud del valor (máximo 4 iniciales + 2 finales), y cualquier valor de 8 caracteres o menos se reemplaza con una máscara de ancho fijo — así una contraseña típica se muestra como ********, mientras que una clave de almacenamiento de 88 caracteres sigue siendo identificable como AAAA**********AA. Las cadenas de contexto se redactan antes de truncarse, y cada secreto encontrado en una línea se redacta del contexto de todos los hallazgos en esa línea, por lo que ningún texto plano sobrevive en un informe. Al revisar falsos positivos, suele ser más rápido ver el valor completo: pasa -ShowSecrets para emitir valores sin redactar en todos los lados (consola, CSV, HTML). La consola y el HTML muestran entonces un banner de advertencia claro, y los informes deben tratarse como material de credenciales vivo:
Invoke-MBSecretScan -Path .\dump -ShowSecrets # raw values, for local triage
Funciona en Windows PowerShell 5.1 y PowerShell 7+ (Windows, Linux, macOS).
Cada ejecución produce tres cosas:
| Salida | Descripción |
|---|---|
| Resumen de consola | Conteos codificados por color según severidad/categoría, más los hallazgos Critical/High principales. |
El cmdlet también emite objetos de hallazgo a la canalización, por lo que puedes posprocesar:
$f = Invoke-MBSecretScan -Path .\dump -Quiet
$f | Where-Object Severity -eq 'Critical' | Format-Table File,Line,RuleName
El conjunto de reglas completo y editable se encuentra en Private/Get-MBSignature.ps1. Cada regla es un [PSCustomObject] con estos campos:
Get-AzDomainInfo exporta las variables de cuentas de automatización y la configuración de aplicaciones como filas Name,Value[,Encrypted]. El secreto vive en la columna Value, mientras que la palabra clave que lo identifica (p. ej. ServiceAccountPwd, dbConnectionString) vive en la columna Name; por lo tanto, una expresión regular simple nunca los ve en la misma "línea" y la palabra clave queda enterrada dentro de un token compuesto sin límite de palabra.
Para archivos .csv / .tsv, el escáner además realiza un emparejamiento estructurado de columnas (Private/Get-MBCsvFinding.ps1):
Encrypted=True se omiten (el valor no es texto plano).Password o StorageKey), se notifica cada celda que no sea un marcador de posición.Los valores que ya cubre una regla de alta confianza (cadenas de conexión, claves de almacenamiento, SAS) se difieren al paso de línea sin procesar para una redacción más estricta, y los hallazgos se deduplican por categoría para que el mismo secreto nunca se notifique dos veces. Si un archivo no se puede analizar como CSV, el escáner recurre automáticamente al escaneo normal de líneas sin procesar.
-ScanValues)El emparejamiento anterior se basa en el nombre de una configuración. Para detectar también secretos almacenados bajo un nombre sin significado (p. ej. Config1 = P@ssw0rd2026!), pasa -ScanValues. Inspecciona el contenido de las celdas de valor con dos heurísticas conservadoras de severidad Low:
!@#$%^&* …) además de letras y otra clase. Se ignoran los valores con estilo de identificador como Standard_D2s_v3 (cuyos únicos símbolos son _ - .).-MinEntropy. Se omiten rutas / URL / ID de recursos (cualquier cosa que contenga / o \) para evitar marcar ID de recursos.En las tablas Name/Value escanea la columna Value; en las tablas de formato libre escanea todas las celdas. Esto cambia una mayor recuperación por más falsos positivos, por lo que está desactivado de forma predeterminada — actívalo para un barrido más profundo y luego revisa los hallazgos Low.
Los volcados de Azure están llenos de cadenas largas de apariencia aleatoria que no son secretos. El escáner las filtra:
GUIDs (ID de suscripción / inquilino / recurso / objeto) nunca se marcan.
Marcadores de posición y formas de valor no secretas — ********, null, <provide-at-deploy>, true/false, caracteres repetidos, tokens de plantilla (${var}, %VAR%), objetos/arrays JSON ({...}, [...], incluidos los multilínea), fechas/marcas de tiempo y nombres de tipo/colección .NET serializados (p. ej., una columna Secrets de un conjunto de escalado de VM que se muestra como System.Collections.Generic.List1[...VaultSecretGroup]) — se omiten. Ten en cuenta que esto se basa en la forma: una columna Secrets` que contiene un valor real en texto plano sigue marcándose.
Campos benignos de metadatos de contraseña — columnas de directorio cuyo nombre contiene una palabra clave pero que solo describen la de la contraseña, nunca el secreto en sí (, , , , , …). Son comunes en exportaciones RBAC como / y no se marcan, mientras que una columna realmente llamada sí se marca. Las columnas de permisos de política de acceso de Key Vault (, , …) — que contienen verbos de permiso como — también se ignoran.
MicroBurstSecretsHunter.psd1 Module manifest
MicroBurstSecretsHunter.psm1 Module loader
Scan-MicroBurst.ps1 Convenience wrapper script
Public/
Invoke-MBSecretScan.ps1 Main cmdlet (file walk, matching, reporting)
Private/
Get-MBSignature.ps1 Detection rule set (edit to extend)
Get-MBCsvFinding.ps1 Structured CSV Name/Value column pairing
MBHelpers.ps1 Entropy, redaction, context rendering,
CSV field escaping, line windowing,
placeholder/GUID filters
Write-MBConsoleSummary.ps1 Console output
New-MBHtmlReport.ps1 HTML report generator
tests/
sample-dump/ Example Get-AzDomainInfo-style fixture
Para probarlo con la muestra incluida:
.\Scan-MicroBurst.ps1 -Path .\tests\sample-dump
Todo lo que el escáner no pudo leer es un punto ciego, y un punto ciego silencioso se lee como "no se ha encontrado nada aquí". Por eso el escáner es explícito al respecto:
-MaxFileSizeMB producen un Write-Warning que los nombra, una línea NOT scanned en el resumen de consola y un banner en el informe HTML.-Verbose para las rutas individuales.AdminPassword más allá de cualquier corte fijo, por lo que las líneas se escanean en ventanas superpuestas de 8000 caracteres en su lugar. Las coincidencias duplicadas de la superposición se eliminan en la deduplicación.-ShowSecrets contienen las credenciales completas en texto plano — guárdalas de forma segura y elimínalas después de la revisión.findings.csv | Una fila por hallazgo (severidad, regla, archivo, línea, valor redactado, contexto) para revisar en Excel. Los campos con contenido escaneado se escapan contra la inyección de fórmulas en hojas de cálculo. |
report.html | Informe HTML autocontenido (sin recursos externos) con tarjetas de severidad, filtro de texto en vivo y alternadores de severidad; se puede compartir con el cliente. |
| Regla | Severidad | Ejemplo de origen en un volcado |
|---|
| Cadena de conexión SQL/BD con contraseña incrustada | Critical | Configuración de App Service, exportaciones de web.config |
| Cadena de conexión de cuenta de Azure Storage / clave de 88 caracteres | Critical | Configuración de aplicaciones, exportaciones de Storage |
SharedAccessKey de Service Bus / Event Hub | Critical | Configuraciones de recursos de mensajería |
| Clave de cuenta de Cosmos DB | Critical | Configuración de aplicaciones |
| Bloque de clave privada PEM | Critical | Exportaciones de Key Vault / certificados |
| Contraseña de Azure Redis Cache | High | Cadenas de conexión de caché |
Secreto de cliente de Azure AD (formato posterior a 2021 …Q~…) | High | Plantillas ARM, configuración de aplicaciones |
Token SAS / parámetro sig= | High | URL SAS de Storage |
| Token JWT / bearer | High | Tokens en caché, configuraciones |
Archivo de certificado / clave presente (.pfx, .pem, .key, …) | High | En cualquier lugar del volcado |
Asignación genérica de password / pwd | High | Variables de automatización, configuración de aplicaciones, parámetros ARM |
Asignación genérica de secret / client_secret | High | Configuración de aplicaciones, plantillas |
| Clave de acceso AWS / tokens de GitHub / Slack | High/Med | Credenciales externas almacenadas en aplicaciones de Azure |
api_key / access_key / connectionstring genéricos | Medium | Configuración de aplicaciones |
| Cadena de alta entropía (heurística) | Low | Red de seguridad para formatos de clave desconocidos — opt-in mediante -IncludeEntropy |
| Campo | Requerido | Propósito |
|---|
Id, Name, Category, Severity | sí | Identidad y cómo se notifica y ordena el hallazgo. |
Pattern | sí | La expresión regular. Se compila una vez por escaneo. |
ValueGroup | sí | Qué grupo de captura contiene el secreto (0 = coincidencia completa). Impulsa la redacción. |
MultiLine | no | Evalúa contra el texto completo del archivo en lugar de línea por línea (bloques PEM). Se notifica cada coincidencia, no solo la primera. |
CaseSensitive | no | Opta por no usar la compilación IgnoreCase predeterminada. Establécelo para formatos definidos con distinción de mayúsculas y minúsculas (AKIA, ghp_, eyJ, Q~); sin ello, coinciden imitaciones con mayúsculas arbitrarias. |
Redact | no | Establece $false cuando el valor capturado es una etiqueta en lugar de un secreto (una línea de cabecera PEM, un nombre de archivo de certificado) para que aparezca textual en lugar de enmascarado hasta quedar ilegible. El valor predeterminado es redactar. |
PasswordProfilePasswordPoliciesForceChangePasswordNextSignInLastPasswordChangeDateTimePasswordExpirationDateTimeInheritedOwners.csvInheritedContributors.csvPasswordPermissionsToSecretsStrPermissionsToKeysStrGet, List, Set, DeleteExpresiones de código y plantillas — cuando password/secret/etc. es un nombre de variable o propiedad que apunta a una expresión en lugar de un literal, el valor capturado se omite: llamadas a cmdlets de PowerShell (Get-RandomPassword 8, Get-AzKeyVaultSecret ...), referencias a variables incluidas las de ámbito ($result, $kv.Secrets, $global:clientSecret, $env:KEY), subexpresiones ((-join $x)) y referencias ARM / Logic App (@{body(...)}, @body(...), [parameters('...')]). Común en runbooks de automatización y definiciones de Logic Apps.
Las formas ambiguas aquí — $var, (expr), Verbo-Sustantivo — solo se descartan en archivos que realmente contienen código (.ps1, .json, .tf, .yaml, …). Una contraseña es muy a menudo una referencia de variable válida ($ummer2026, $ecretPass1), por lo que aplicar ese filtro a las celdas de valor CSV descartaba secretos reales. Los marcadores de plantilla inequívocos (@{, @body(, [parameters() se filtran en todas partes.
Adyacencia de encabezados de columna — las reglas genéricas de palabra clave = valor solo tratan : y = como separadores (no ,), por lo que un encabezado CSV como ...,AdminPassword,Secrets,... ya no captura el nombre de la siguiente columna como contraseña. Los pares Name,Value separados por comas siguen estando cubiertos por el emparejamiento CSV estructurado.
Las rutas de ID de recurso se dividen en segmentos cortos en lugar de tratarse como un único token de alta entropía.
Los formatos de credenciales sensibles a mayúsculas (AWS AKIA…, GitHub ghp_…, JWT eyJ…, Azure AD …Q~…) se comparan distinguiendo mayúsculas y minúsculas, por lo que las imitaciones con mayúsculas arbitrarias como akiaijklmnopqrstuvwx no se notifican. Las reglas de palabras clave (password=, AccountKey=) permanecen sin distinguir mayúsculas y minúsculas.
La heurística de entropía está desactivada de forma predeterminada — produce hallazgos Low ruidosos, por lo que optas por ella con -IncludeEntropy para un barrido más profundo. Incluso entonces solo se activa en tokens que parecen material de clave (letras y dígitos mezclados o marcadores base64), por lo que los identificadores camelCase como networkSecurityGroups se ignoran. Sube aún más el listón con -MinEntropy 4.5.
| Parámetro | Predeterminado | Propósito |
|---|
-Path | (obligatorio) | Carpeta raíz de la salida de MicroBurst. |
-OutputDirectory | carpeta con marca de tiempo | Dónde se escriben los informes (nunca se escanea). No puede ser la propia raíz del escaneo; una carpeta anidada dentro de ella muestra una advertencia. |
-IncludeEntropy | desactivado | Opta por el paso heurístico de alta entropía (añade hallazgos Low). |
-MinEntropy | 4.0 | Umbral de entropía de Shannon (bits/char) para la heurística. |
-ScanValues | desactivado | Inspecciona también el contenido de las celdas de valor CSV en busca de secretos bajo nombres inocuos (Low, mayor recuperación). |
-ShowSecrets | desactivado | Emite valores sin redactar en toda la salida para acelerar la revisión de falsos positivos. Los informes se convierten en material de credenciales vivo. |
-MaxFileSizeMB | 50 | Omite archivos más grandes que esto. Los archivos omitidos se avisan y se cuentan en el resumen y en el informe HTML. |
-IncludeExtension | tipos de texto comunes | Sobrescribe qué tipos de archivo se escanean (el punto inicial es opcional). |
-NoCsv / -NoHtml | desactivado | Omite un formato de informe. |
-Quiet | desactivado | Suprime el resumen de consola (los objetos aún se devuelven). |