
Analizza i dump di domini Azure esportati alla ricerca di password in chiaro, stringhe di connessione, chiavi di storage e altri segreti; genera report CSV/HTML oscurati per flussi di lavoro di audit in sola lettura.
Uno scanner PowerShell che esamina l'output di MicroBurst
Get-AzDomainInfo alla ricerca di password in chiaro, chiavi, stringhe di connessione e
altri segreti che non dovrebbero mai rimanere non cifrati in un ambiente Azure.
Progettato per flussi di lavoro di audit in sola lettura: raccogli un dump del
dominio con MicroBurst (l'accesso Reader è sufficiente per Get-AzDomainInfo), poi
punta questo strumento alla cartella di output. Non tocca affatto Azure stesso —
legge solo i file che hai già esportato. I valori segreti vengono oscurati in ogni
report, quindi l'output è sicuro da allegare ai finding.
# Clone / copy this folder, then from a PowerShell prompt:
.\Scan-MicroBurst.ps1 -Path .\MicroBurst-2026 -Verbose
Oppure importa il modulo e usa il cmdlet direttamente:
Import-Module .\MicroBurstSecretsHunter.psd1 -Force
Invoke-MBSecretScan -Path .\MicroBurst-2026
I report vengono scritti in una cartella con timestamp () nella directory corrente, a meno che non passi .
MBSecretScan-<timestamp>-OutputDirectoryPer impostazione predefinita ogni valore viene oscurato, quindi i report sono
sicuri da condividere. I caratteri rivelati sono limitati a un quarto della
lunghezza del valore (massimo 4 iniziali + 2 finali), e qualsiasi valore di 8
caratteri o meno viene sostituito con una maschera a larghezza fissa — quindi una
password tipica appare come ********, mentre una chiave di archiviazione lunga 88
caratteri resta identificabile come AAAA**********AA. Le stringhe di contesto
vengono oscurate prima di essere troncate, e ogni segreto trovato su una riga
viene oscurato dal contesto di ogni finding su quella riga, quindi nessun testo in
chiaro sopravvive in un report. Quando fai triage dei falsi positivi, spesso è più
veloce vedere il valore completo — passa -ShowSecrets per emettere valori non
oscurati ovunque (console, CSV, HTML). Console e HTML mostrano quindi un chiaro
banner di avviso, e i report devono essere trattati come materiale di credenziali
attive:
Invoke-MBSecretScan -Path .\dump -ShowSecrets # raw values, for local triage
Funziona su Windows PowerShell 5.1 e PowerShell 7+ (Windows, Linux, macOS).
Ogni esecuzione produce tre cose:
| Output | Descrizione |
|---|---|
| Riepilogo console | Conteggi con codifica a colori per gravità/categoria più i principali finding Critical/High. |
findings.csv | Una riga per finding (gravità, regola, file, riga, valore oscurato, contesto) per il triage in Excel. I campi che contengono contenuto scansionato sono protetti contro l'iniezione di formule nei fogli di calcolo. |
report.html | Report HTML autonomo (nessuna risorsa esterna) con card di gravità, filtro di testo in tempo reale e interruttori di gravità — condivisibile con il cliente. |
Il cmdlet emette inoltre oggetti finding nella pipeline, così puoi fare post-elaborazione:
$f = Invoke-MBSecretScan -Path .\dump -Quiet
$f | Where-Object Severity -eq 'Critical' | Format-Table File,Line,RuleName
| Regola | Gravità | Esempio di origine in un dump |
|---|---|---|
| Stringa di connessione SQL/DB con password incorporata | Critical | Impostazioni di App Service, esportazioni web.config |
| Stringa di connessione dell'account di archiviazione Azure / chiave a 88 caratteri | Critical | Impostazioni dell'app, esportazioni di Storage |
SharedAccessKey di Service Bus / Event Hub | Critical | Configurazioni delle risorse di messaggistica |
| Chiave dell'account Cosmos DB | Critical | Impostazioni dell'app |
| Blocco di chiave privata PEM | Critical | Esportazioni Key Vault / certificati |
| Password della cache Azure Redis | High | Stringhe di connessione della cache |
Client secret di Azure AD (formato post-2021 …Q~…) | High | Template ARM, impostazioni dell'app |
Token SAS / parametro sig= | High | URL SAS di Storage |
| Token JWT / bearer | High | Token in cache, configurazioni |
File di certificato/chiave presente (.pfx, .pem, .key, …) | High | Ovunque nel dump |
Assegnazione generica di password / pwd | High | Variabili di automazione, impostazioni dell'app, parametri ARM |
Assegnazione generica di secret / client_secret | High | Impostazioni dell'app, template |
| Chiavi di accesso AWS / token GitHub / Slack | High/Med | Credenziali esterne archiviate nelle app Azure |
api_key / access_key / connectionstring generici | Medium | Impostazioni dell'app |
| Stringa ad alta entropia (euristica) | Low | Rete di sicurezza per formati di chiave sconosciuti — attivabile tramite -IncludeEntropy |
Il set di regole completo ed editabile si trova in Private/Get-MBSignature.ps1. Ogni
regola è un [PSCustomObject] con questi campi:
| Campo | Obbligatorio | Scopo |
|---|---|---|
Id, Name, Category, Severity | sì | Identità e come il finding viene riportato e ordinato. |
Pattern | sì | La regex. Compilata una volta per scansione. |
ValueGroup | sì | Quale gruppo di cattura contiene il segreto (0 = intera corrispondenza). Guida l'oscuramento. |
MultiLine | no | Valuta sul testo dell'intero file invece che riga per riga (blocchi PEM). Viene riportata ogni corrispondenza, non solo la prima. |
CaseSensitive | no | Disattiva la compilazione predefinita IgnoreCase. Impostalo per formati definiti con distinzione tra maiuscole e minuscole (AKIA, ghp_, eyJ, Q~) — senza, corrispondono anche stringhe simili con maiuscole/minuscole arbitrarie. |
Redact | no | Imposta $false quando il valore catturato è un'etichetta piuttosto che un segreto (una riga di intestazione PEM, un nome di file di certificato), così appare testualmente invece di essere mascherato fino a diventare illeggibile. L'impostazione predefinita è l'oscuramento. |
Get-AzDomainInfo esporta le variabili degli automation account e le impostazioni
delle app come righe Name,Value[,Encrypted]. Il segreto vive nella colonna Value,
mentre la parola chiave che lo identifica (es. ServiceAccountPwd, dbConnectionString)
vive nella colonna Name — quindi una semplice regex non li vede mai sulla stessa
"riga" e la parola chiave è sepolta dentro un token composto senza confine di parola.
Per i file .csv / .tsv lo scanner esegue inoltre l'associazione strutturata
delle colonne (Private/Get-MBCsvFinding.ps1):
Encrypted=True vengono saltate (il valore non è testo in chiaro).Password o StorageKey), viene riportata ogni cella
che non sia un placeholder.I valori già coperti da una regola ad alta confidenza (stringhe di connessione, chiavi di archiviazione, SAS) vengono rinviati al passaggio sulle righe grezze per un oscuramento più stretto, e i finding vengono de-duplicati per categoria così lo stesso segreto non viene mai riportato due volte. Se un file non può essere analizzato come CSV, lo scanner ripiega automaticamente sulla normale scansione delle righe grezze.
-ScanValues)L'associazione di cui sopra fa leva sul nome di un'impostazione. Per cogliere
anche i segreti archiviati sotto un nome senza significato (es.
Config1 = P@ssw0rd2026!), passa -ScanValues. Esamina il contenuto delle
celle dei valori con due euristiche conservative a gravità Low:
!@#$%^&* …) più lettere e un'altra classe. I valori in stile
identificatore come Standard_D2s_v3 (i cui unici simboli sono _ - .) vengono ignorati.-MinEntropy. Percorsi / URL / ID di risorse (qualsiasi cosa contenga / o \)
vengono saltati per evitare di segnalare gli ID di risorse.Nelle tabelle Name/Value scansiona la colonna Value; nelle tabelle a forma libera
scansiona ogni cella. Questo scambia una recall più alta con più falsi positivi,
quindi è disattivata per impostazione predefinita — attivala per una scansione
più approfondita, poi fai il triage dei finding Low.
I dump di Azure sono pieni di lunghe stringhe dall'aspetto casuale che non sono segreti. Lo scanner le filtra:
GUID (ID di sottoscrizione / tenant / risorsa / oggetto) non vengono mai segnalati.
Placeholder e forme di valore non segrete — ********, null,
<provide-at-deploy>, true/false, caratteri ripetuti, token di template
(${var}, %VAR%), oggetti/array JSON ({...}, [...], inclusi quelli su più
righe), date/timestamp e nomi serializzati di tipi/collezioni .NET
(es. una colonna Secrets di un set di scalabilità di VM che appare come
System.Collections.Generic.List1[...VaultSecretGroup]) — vengono saltati. Nota che questo si basa sulla forma: una colonna Secrets` che contiene un valore
effettivamente in chiaro viene comunque segnalata.
Campi benigni di metadati della password — colonne di directory il cui nome
contiene una parola chiave ma descrivono solo policy/stato della password, mai
il segreto stesso (PasswordProfile, PasswordPolicies,
ForceChangePasswordNextSignIn, LastPasswordChangeDateTime,
PasswordExpirationDateTime, …). Sono comuni nelle esportazioni RBAC come
InheritedOwners.csv / InheritedContributors.csv e non vengono segnalate, mentre
una colonna realmente chiamata Password lo è ancora. Anche le colonne dei permessi
delle access policy di Key Vault (PermissionsToSecretsStr, PermissionsToKeysStr, …)
— che contengono verbi di permesso come Get, List, Set, Delete — vengono ignorate.
Espressioni di codice e template — quando password/secret/ecc. è un nome
di variabile o proprietà che punta a un'espressione piuttosto che a un letterale,
il valore catturato viene saltato: chiamate a cmdlet PowerShell
(Get-RandomPassword 8, Get-AzKeyVaultSecret ...), riferimenti a variabili
inclusi quelli con ambito ($result, $kv.Secrets, $global:clientSecret,
$env:KEY), sotto-espressioni ((-join $x)) e riferimenti ARM / Logic App
(@{body(...)}, @body(...), [parameters('...')]). Comuni nei runbook di
automazione e nelle definizioni di Logic App.
Le forme ambigue qui — $var, , — vengono scartate solo nei
file che contengono effettivamente codice (, , , , …).
Una password è molto spesso un riferimento a variabile valido (,
), quindi applicare quel filtro alle celle dei valori CSV portava a
scartare segreti reali. I marcatori di template inequivocabili (, ,
) vengono filtrati ovunque.
Adiacenza delle intestazioni di colonna — le regole generiche keyword = value
trattano solo : e = come separatori (non ,), quindi un'intestazione CSV come
...,AdminPassword,Secrets,... non cattura più il nome della colonna successiva
come password. Le coppie Name,Value separate da virgola sono ancora coperte
dall'associazione strutturata CSV.
I percorsi degli ID di risorsa vengono suddivisi in segmenti brevi invece di essere trattati come un unico token ad alta entropia.
I formati di credenziali con distinzione tra maiuscole e minuscole (AWS
AKIA…, GitHub ghp_…, JWT eyJ…, Azure AD …Q~…) vengono confrontati
rispettando maiuscole/minuscole, quindi stringhe simili con maiuscole arbitrarie
come akiaijklmnopqrstuvwx non vengono riportate. Le regole per parole chiave
(password=, AccountKey=) restano senza distinzione tra maiuscole e minuscole.
L'euristica dell'entropia è disattivata per impostazione predefinita — produce
finding Low rumorosi, quindi la attivi con -IncludeEntropy per una scansione più
approfondita. Anche in quel caso scatta solo su token che sembrano materiale di chiave
(lettere+cifre miste o marcatori base64), quindi identificatori camelCase come
networkSecurityGroups vengono ignorati. Alza ulteriormente l'asticella con
-MinEntropy 4.5.
| Parametro | Predefinito | Scopo |
|---|---|---|
-Path | (obbligatorio) | Cartella principale dell'output di MicroBurst. |
-OutputDirectory | cartella con timestamp | Dove vengono scritti i report (mai scansionata). Non può essere la radice della scansione stessa; una cartella annidata al suo interno genera un avviso. |
-IncludeEntropy | off | Attiva il passaggio euristico ad alta entropia (aggiunge finding a gravità Low). |
-MinEntropy | 4.0 | Soglia di entropia di Shannon (bit/char) per l'euristica. |
-ScanValues | off | Ispeziona anche il contenuto delle celle dei valori CSV alla ricerca di segreti sotto nomi innocui (gravità Low, recall più alta). |
-ShowSecrets | off | Emette valori non oscurati in tutti gli output per accelerare il triage dei falsi positivi. I report diventano materiale di credenziali attive. |
-MaxFileSizeMB | 50 | Salta i file più grandi di questa dimensione. I file saltati vengono segnalati con un avviso e conteggiati nel riepilogo e nel report HTML. |
-IncludeExtension | tipi di testo comuni | Sostituisce i tipi di file da scansionare (il punto iniziale è opzionale). |
-NoCsv / -NoHtml | off | Salta un formato di report. |
-Quiet | off | Sopprime il riepilogo in console (gli oggetti vengono comunque restituiti). |
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
Per provarlo con il sample incluso:
.\Scan-MicroBurst.ps1 -Path .\tests\sample-dump
Qualsiasi cosa che lo scanner non ha potuto leggere è un punto cieco, e un punto cieco silenzioso si legge come "non è stato trovato nulla qui". Quindi lo scanner li segnala esplicitamente:
-MaxFileSizeMB producono un Write-Warning che li nomina, una
riga NOT scanned nel riepilogo in console e un banner nel report HTML.-Verbose per i singoli percorsi.AdminPassword oltre qualsiasi limite fisso, quindi
le righe vengono scansionate in finestre sovrapposte di 8000 caratteri. I risultati
duplicati dovuti alla sovrapposizione collassano nella de-duplicazione.-ShowSecrets contengono le credenziali complete in chiaro
— conservale in modo sicuro ed eliminale dopo il triage.(expr)Verb-Noun.ps1.json.tf.yaml$ummer2026$ecretPass1@{@body([parameters(