-
Notifications
You must be signed in to change notification settings - Fork 3
/
templateScan.ps1
390 lines (298 loc) · 16.8 KB
/
templateScan.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
<#
###########################################################################################
# #
# Deployment Grazor - Used to discover secrets in insecure Azure Deployments #
# #
###########################################################################################
# #
# #
# Written by: Javan Joshua Mnjama #
# @east-african-techguy #
# #
# #
###########################################################################################
Versions Notes:
Version 1.0 - 04-06-22
###########################################################################################
HOW TO INSTALL AZURE POWERSHELL MODULE:
Guide for installing Azure "AZ" PowerShell Module:
https://docs.microsoft.com/en-us/powershell/azure/install-az-ps
If local admin (PowerShell command):
Install-Module -Name Az -AllowClobber
Install-Module AzureAD -AllowClobber
Else:
Install-Module -Name Az -AllowClobber -Scope CurrentUser
Install-Module AzureAD -AllowClobber -Scope CurrentUser
###########################################################################################
HOW TO RUN Deployment Grazor:
1) Download/sync locally the script file templateScan.ps1
2) Open PowerShell in the Deployment Grazor folder with the permission to run scripts:
"powershell -ExecutionPolicy Bypass -NoProfile"
3) Import-Module ./DeploymentGrazor.ps1
4) Run Start-DeploymentScan
5) Results of scan will be written in a txt file in the directory used to execute the script
#>
$DeploymentGrazorVersion = "v1.0"
$DeploymentGrazor = @"
-------------------------------------------------------------------------------
____ _____ ____ _ _____ ____ __ _____ _ _ _____
| _ \| ____| _ \| | / _ \ \ / / \/ | ____| \ | |_ _|
| | | | _| | |_) | | | | | \ V /| |\/| | _| | \| | | |
| |_| | |___| __/| |__| |_| || | | | | | |___| |\ | | |
|____/|_____|_| |_____\___/ |_| |_| |_|_____|_| \_| |_|
____ ____ _ ________ ____
/ ___| _ \ / \ |__ / _ \| _ \
| | _| |_) | / _ \ / / | | | |_) |
| |_| | _ < / ___ \ / /| |_| | _ <
\____|_| \_\/_/ \_\/____\___/|_| \_\
"@
$Author = @"
-------------------------------------------------------------------------------
Author: Javan Joshua Mnjama
@east-african-techguy
-------------------------------------------------------------------------------
"@
Write-Output $DeploymentGrazor
Write-Output "`n *** Welcome to Deployment Grazor $DeploymentGrazorVersion ***`n"
Write-Output "`n *** Used to discover secrets in insecure Azure Deployments :)`n"
Write-Output $Author
# Check if the PowerShell Azure Module exists on the machine
function Check-AzureModule {
$oneAzureModuleExist = $true
# Try loading the AZ PowerShell Module
try {
$azModule = Get-InstalledModule -Name Az -ErrorAction Stop
}
Catch {
Write-Host "`nCouldn't find the Azure `"AZ`" PowerShell Module" -ForegroundColor Yellow
Write-Host "The tool will prompt you and install it using the `"Install-Module -Name Az`" command" -ForegroundColor Yellow
if ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) {
Install-Module -Name Az -AllowClobber
}
else {
Install-Module -Name Az -AllowClobber -Scope CurrentUser
}
}
try {
$azModule = Get-InstalledModule -Name Az -ErrorAction Stop
if ($azModule) {
Write-Host "`n [+] Great, Azure `"AZ`" PowerShell Module exists`n"
}
}
catch {
Write-Host "`nEncountered an error - couldn't find the Azure `"AZ`" PowerShell Module" -BackgroundColor Red
Write-Host "Please install Azure Az PowerShell Module (requires PowerShell version 5.1+)" -BackgroundColor Red
Write-Host "Installation guideline:" -BackgroundColor Red
Write-Host "https://docs.microsoft.com/en-us/powershell/azure/install-az-ps" -BackgroundColor Red
$oneAzureModuleExist = $false
}
}
# Connect to the target Azure environment
function Connect-AzureEnvironment {
try {
$answer = "n"
$AzContext = Get-AzContext | Where-Object { ($_.tenant) -or ($_.TenantId) }
if ($AzContext.Account) {
Write-Host "The current Azure account context is set for:"
Write-Host ($AzContext | select Name, Account, Environment | Format-List | Out-String) -NoNewline
$answer = Read-Host "Do you want to use this Azure Account context? Press (y/Y or n/N)"
}
if ($answer.ToLower() -notmatch "y") {
$AzAllCachedContext = Get-AzContext -ListAvailable
$AzCachedContext = $AzAllCachedContext | Where-Object { ($_.Tenant) -or ($_.TenantId) }
if ($AzCachedContext) {
Write-Host "The follwoing Azure user/s are available through the cache:`n"
$counter = 0
$AzCachedContext | foreach {
$counter++
$contextAccount = $_.Account.id
$contextName = $_.Name
$contextNameEx = "*" + $contextAccount + "*"
if ($contextName -like $contextNameEx) {
Write-Host "$counter) Name: $contextName"
}
else {
Write-Host "$counter) Name: $contextName - $contextAccount"
}
}
$contextAnswer = Read-Host "`n Do you want to use one of the above cached users?`nPress the user's number from above (or n/N for chosing a new user)"
if ($contextAnswer.ToString() -le $counter) {
$contextNum = [int]$contextAnswer
$contextNum--
$chosenAccount = $AzCachedContext[$contextNum].Account.id
Write-Host "`nYou chose to proceed with $chosenAccount"
Set-AzContext -Context $AzCachedContext[$contextNum] -ErrorAction Stop > $null
return $true
}
}
Write-Host "Please connect to your desired Azure environment"
Write-Host "These are the available Azure environments:"
$AzEnvironment = Get-AzEnvironment | select Name, ResourceManagerUrl
Write-Host ($AzEnvironment | Format-Table | Out-String) -NoNewline
$answer = read-host "Do you use the US-based `"AzureCloud`" environment? Press (y/Y or n/N)"
$rand = Get-Random -Maximum 10000
if ($answer.ToLower() -match "y") {
Connect-AzAccount -ContextName "Azure$rand" -ErrorAction Stop > $null
}
else {
$AzEnvironment = Read-Host "Ok, please write your Azure environment Name from the list above.`nAzure environment Name"
Connect-AzAccount -ContextName "Azure$rand" -Environment $AzEnvironment -ErrorAction Stop > $null
}
}
}
catch {
Write-Host "Encountered an error - check again the inserted Azure Credentials" -BackgroundColor red
Write-Host "There was a problem when trying to access the target Azure Tenant\Subscription" -BackgroundColor Red
Write-Host "Please try again... and use a valid Azure user"
Write-Host "You can also try different Azure user credentials or test the scan on a different environment"
return $false
}
Write-Host "`n [+] Got valid Azure credentials"
return $true
}
# Main Function to Scan Deployment Templates
function Run-SubscriptionScan {
$count = 0
$deploymentCount = 0
# Secret Test Cases to check in deployment templates
$secretTestCases = 'authkey', 'instrumentationkey', 'password', 'clientsecret', 'connectionstring'
foreach ($id in $subscriptionList) {
$resourceGroup = Get-AzResourceGroup
while ($count -lt $resourceGroup.count) {
# Pulls all the deployment template from a resource group
$deployment = Get-AzResourceGroupDeployment -ResourceGroupName $resourceGroup[$count].ResourceGroupName
if ($deployment) {
while ($deploymentCount -lt $deployment.Count) {
$Parameters_Secret_Collection = $deployment[$deploymentCount]
# This checks for secrets in the parameters section of deployments templates
foreach ($parData in $Parameters_Secret_Collection) {
if ( $parData.Parameters) {
foreach ($key in $parData.Parameters) {
foreach ($i in $key.Keys) {
foreach ($item in $secretTestCases) {
# This checks for secrets using the secrets test cases. $secretVal is used to elimate secureStrings
$secretVal = $key[$i].Type
if (($i.ToLowerInvariant() -like "*" + $item + "*") -and ($secretVal -eq 'String')) {
Write-Output "===============================================================================" | Out-File -Append "./results.txt"
Write-Output "Subscription ID :" $id | Out-File -Append "./results.txt"
Write-Output "===============================================================================" | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output "ResourceGroup ..." $resourceGroup[$count].ResourceGroupName | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output " Secret in Deployment Template" $Deployment[$deploymentCount].DeploymentName | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
# writes output and appends to file
Write-Output $i : $key[$i].Value | Out-File -Append "./results.txt"
}
}
}
}
}
}
# Outputs Secret Check
$Outputs_Secrets_Collection = $deployment[$deploymentCount].Outputs
foreach ($data in $Outputs_Secrets_Collection) {
foreach ($item in $secretTestCases) {
if ($data.Keys -like "*" + $item + "*") {
Write-Output "===============================================================================" | Out-File -Append "./results.txt"
Write-Output "Subscription ID :" $id | Out-File -Append "./results.txt"
Write-Output "===============================================================================" | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output "ResourceGroup ..." $resourceGroup[$count].ResourceGroupName | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output " Secret in Deployment Template" $Deployment[$deploymentCount].DeploymentName | Out-File -Append "./results.txt"
Write-Output "==============================================" | Out-File -Append "./results.txt"
Write-Output $data.Keys ":" $data.Values | Out-File -Append "./results.txt"
}
}
}
$deploymentCount ++
}
}
$count ++
}
Write-Output "Output written to file ./results.txt"
}
}
function Scan-Templates {
[CmdletBinding()]
param(
[switch]
$UseCurrentCred,
[string]
$ScanSubscriptionId
)
$CloudShellMode = $false
try {
$cloudShellRun = Get-CloudDrive
if ($cloudShellRun) {
$CloudShellMode = $true
}
}
catch {
$CloudShellMode = $false
}
$AzModule = $true
if (-not $CloudShellMode) {
$AzModule = Check-AzureModule
}
if ($AzModule -eq $false) {
Return
}
if (-not $UseCurrentCred) {
$AzConnection = Connect-AzureEnvironment
if ($AzConnection -eq $false) {
Return
}
$currentAzContext = Get-AzContext
}
else {
$currentAzContext = Get-AzContext
}
if ($CloudShellMode) {
try {
Connect-AzureADservice
}
catch {
Write-Host "Couldn't connect using the `"Connect-AzureADservice`" API call,`nThe tool will connect with `"Connect-AzureActiveDirectory `" call"
$AzConnection = Connect-AzureActiveDirectory -AzContext $currentAzContext
}
}
try {
Write-host "`n [+] Running the scan with user: "$currentAzContext.Account
$tenantList = Get-AzTenant
Write-Host "`nAvailable Tenant ID/s:`n"
Write-Host " "($tenantList.Id | Format-Table | Out-String)
if ($ScanSubscriptionId) {
$subscriptionList = Get-AzSubscription -subscriptionId $ScanSubscriptionId
}
else {
$subscriptionList = Get-AzSubscription | select Name, Id, TenantId
}
if ($subscriptionList) {
Write-Host "Available Subscription\s:"
Write-Host ($subscriptionList | Format-Table | Out-String) -NoNewline
}
}
catch {
Write-Host "Encountered an error - check again the inserted Azure Credentials" -BackgroundColor red
Write-Host "There was a problem when trying to access the target Azure Tenant\Subscription" -BackgroundColor Red
Write-Host "Please try again.."
Write-Host "You can also try different Azure user credentials or test the scan on a different environment"
Return
}
$AzContextAutosave = (Get-AzContextAutosaveSetting).CacheDirectory
if ($AzContextAutosave -eq "None") {
Enable-AzContextAutosave
}
# Scan all the available subscription\s
$subscriptionList | foreach {
Write-Host "`n [+] Scanning Subscription Name: "$($_.Name)", ID: $($_.Id)"
Set-AzContext -SubscriptionId $_.id > $null
$paramSplat = @{}
$paramSplat.add('subscriptionId', $_.id)
Run-SubscriptionScan @paramSplat
}
}