-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstep.ps1
313 lines (250 loc) · 12.7 KB
/
step.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
<#
Author(s): Bruce Lee, Grant Killian, Kelly Rusk, Jimmy Rudley
Colaborator: Diego Saavedra San Juan
Created Date: August 4, 2016
Modified Date: August 5, 2016
This is the Rackspace Managed Services for Sitecore (https://www.rackspace.com/digital/sitecore) script for security hardening a Sitecore environment
If the Execution Policy does not allow execution, you may need to run the following interactively to allow a scoped session bypass.
This is secure as it requires interaction on server and cannot be executed from a script:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
1. Deny anonymous users access to key folders
2. Disable client RSS feeds
3. Secure the file upload functionality
4. Improve the security of the website folder
5. Increase login security
6. Limit access to certain file types
7. Protect PhantomJS
8. Protect media requests
9. Remove header information from responses sent by your website
#>
param(
[Parameter(Mandatory=$true)]
[string]$siteName, # The name of the site as seen in IIS
[Parameter(Mandatory=$true)]
[string]$mediaRequestSharedSecretGuid, # The GUID to protect the media requests with, using Shared Secret
[Parameter(Mandatory=$false)]
[string]$extraInclude, # The subpath to the folder where the extra included files will be
[Parameter(Mandatory=$false)]
[string]$role="cm", # The role the instance has. One of CM or CD
[Parameter(Mandatory=$false)]
[string]$dataFolderLocation, # The path to the Sitecore data folder.
[Parameter(Mandatory=$false)]
[string]$stepsString="123456789") # Optional string specifying steps to apply.
$site = get-website -name $siteName
$sitecoreRoot = $site.physicalPath
$sitecoreAppIncludeDirectory = "{0}\app_config\include" -f $sitecoreRoot
if ( $extraInclude -eq $null -or $extraInclude -eq "" )
{ $extraInclude = $sitecoreAppIncludeDirectory+"\zz" }
# read in Web.config
$webConfigPath = "{0}\web.config" -f $site.physicalPath
Write-Host 'Steps string is '$stepsString
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Deny anonymous users access to key folders
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("1") )
{
$filterString = "/system.Webserver/security/authentication/anonymousauthentication"
$app_ConfigLocation = "{0}/App_Config" -f $siteName
$adminLocation = "{0}/sitecore/admin" -f $siteName
$debugLocation = "{0}/sitecore/debug" -f $siteName
$ShellWebserviceLocation = "{0}/sitecore/shell/webservice" -f $siteName
Set-WebConfigurationProperty -filter $filterString -name enabled -value false -Location $app_ConfigLocation
Set-WebConfigurationProperty -filter $filterString -name enabled -value false -Location $adminLocation
Set-WebConfigurationProperty -filter $filterString -name enabled -value false -Location $debugLocation
Set-WebConfigurationProperty -filter $filterString -name enabled -value false -Location $ShellWebserviceLocation
Write-Output "Step 1 completed - Deny anonymous users access to key folders"
}
else
{
Write-Output "Step 1 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Disable client RSS feeds
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("2") )
{
[xml] $webConfigXML = Get-Content $webConfigPath
#remove the following handler in the <httpHanderls> section in the web.config
$targetName = "Sitecore.FeedRequestHandler"
$nodePath = "configuration/system.webServer/handlers/add[@name='{0}']" -f $targetName
$node = $webConfigXML.SelectSingleNode($nodePath)
if($node -ne $null)
{
$webConfigXML.configuration.'system.webServer'.handlers.RemoveChild($node)
}
$webConfigXML.Save($webConfigPath)
Write-Output "Step 2 completed - Disable client RSS feeds"
}
else
{
Write-Output "Step 2 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Secure the file upload functionality
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("3") )
{
#Deny Script and Execute permission on /upload folder
$psPath = "MACHINE/WEBROOT/APPHOST/{0}/upload" -f $site.name
$filter = "system.webServer/handlers/@AccessPolicy"
Set-WebConfiguration -Filter $filter -Value "Read" -PSPath $psPath
#Deny Script and Execute permission on /temp folder
$psPath = "MACHINE/WEBROOT/APPHOST/{0}/temp" -f $site.name
$filter = "system.webServer/handlers/@AccessPolicy"
Set-WebConfiguration -Filter $filter -Value "Read" -PSPath $psPath
#Remove the SitecoreUploadWatcher
$xml = [xml](get-content $webConfigPath)
foreach( $item in $xml.configuration."system.webServer".modules.add )
{
if( $item.name -eq "SitecoreUploadWatcher" )
{
$xml.configuration."system.webServer".modules.RemoveChild($item);
}
}
$xml.Save($webConfigPath)
$WebsiteBin = "{0}\bin" -f $sitecoreRoot
Copy-Item -Path .\UploadFilter.config -Destination $extraInclude
Copy-Item -Path .\Sitecore.UploadFilter.dll -Destination $WebsiteBin
Write-Output "Step 3 completed - Secure the file upload functionality"
}
else
{
Write-Output "Step 3 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Improve the security of the website folder
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("4") )
{
#This is mostly handled during our scripted install; this is a snippet from those procedures
<# $sitecoreDataDirectory = "D:/outside/of/webroot"
$sitecoreAppIncludeDirectory = "{0}\app_config\include" -f $sitecoreRoot
$rackspaceInclude = $sitecoreAppIncludeDirectory + "\Z.Rackspace"
if( !(test-path $rackspaceInclude) )
{
mkdir $rackspaceInclude
}
$dataFolderConfigPath = "{0}\DataFolder.config.example" -f $sitecoreAppIncludeDirectory
[xml]$dataConfigXML = Get-Content $dataFolderConfigPath
$dataConfigXML.configuration.sitecore.'sc.variable'.attribute.'#text' = $sitecoreDataDirectory
$dataConfigXML.Save($dataFolderConfigPath)
$newFilename = (Get-ChildItem $dataFolderConfigPath).BaseName
Rename-Item -Path $dataFolderConfigPath -NewName $newFilename #>
Write-Output "Step 4 completed - Improve the security of the website folder. Handled on Octopus Step 'Set up Data Folder'"
}
else
{
Write-Output "Step 4 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Increase login security
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("5") )
{
Copy-Item -Path .\IncreaseLoginSecurity.config -Destination $extraInclude
Write-Output "Step 5 completed - Increase login security"
}
else
{
Write-Output "Step 5 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Limit access to certain file types
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("6") )
{
$psPath = "MACHINE/WEBROOT/APPHOST/{0}" -f $site.name
$filter = "system.webServer/handlers/"
if ( (Get-WebHandler -Name "xml (integrated)" -PSPath $psPath).name -eq $null )
{ New-WebHandler -Path *.xml -Verb * -Type "System.Web.HttpForbiddenHandler" -Name "xml (integrated)" -Precondition integratedMode -PSPath $psPath }
if ( (Get-WebHandler -Name "xslt (integrate)" -PSPath $psPath).name -eq $null )
{ New-WebHandler -Path *.xslt -Verb * -Type "System.Web.HttpForbiddenHandler" -Name "xslt (integrate)" -Precondition integratedMode -PSPath $psPath }
if ( (Get-WebHandler -Name "config.xml (integrate)" -PSPath $psPath).name -eq $null )
{ New-WebHandler -Path *.config.xml -Verb * -Type "System.Web.HttpForbiddenHandler" -Name "config.xml (integrate)" -Precondition integratedMode -PSPath $psPath }
if ( (Get-WebHandler -Name "mrt (integrate)" -PSPath $psPath).name -eq $null )
{ New-WebHandler -Path *.mrt -Verb * -Type "System.Web.HttpForbiddenHandler" -Name "mrt (integrate)" -Precondition integratedMode -PSPath $psPath }
Write-Output "Step 6 completed - Limit access to certain file types"
}
else
{
Write-Output "Step 6 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Protect PhantomJS --generally not suitable for Content Management (CM) servers
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("7") )
{
if ( $role.ToUpper() -ne "CM" )
{
$dataFolderValue = "";
if ( $dataFolderLocation -eq $null -or $dataFolderLocation -eq "" )
{
$dataFolderConfigPath = "{0}\App_Config\Include\DataFolder.config" -f $site.physicalPath
[xml] $dataFolderConfigXML = Get-Content $dataFolderConfigPath
$dataFolderValue = $dataFolderConfigXML.configuration.sitecore.'sc.variable'.attribute.'#text'
}
else
{
$dataFolderValue = $dataFolderLocation
}
$phantomToolPath = "{0}\tools\phantomjs" -f $dataFolderValue
if ( Test-Path $phantomToolPath ) { Remove-Item -Recurse -Path $phantomToolPath }
$ProtectPhantomJSPath = ".\ProtectPhantomJS.config"
Copy-Item -Path $ProtectPhantomJSPath -Destination $extraInclude
}
else
{
Write-Output "Step 7 skipped as this is a CM instance"
}
Write-Output "Step 7 completed - Protect PhantomJS"
}
else
{
Write-Output "Step 7 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 8 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Protect Media Requests
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("8") )
{
#set the implementation guid -- the gist just has a placeholder
$downLoadPath = ".\ProtectMediaRequests.config"
(Get-Content $downLoadPath).replace($mediaRequestSharedSecretGuid, "58d36579-94c3-42d8-802f-b7cc62121d47") | Set-Content $downLoadPath
Copy-Item -Path $downLoadPath -Destination $extraInclude
Write-Output "Step 8 completed - Protect Media Requests"
}
else
{
Write-Output "Step 8 skipped - Not in stepsStrings variable"
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STEP 9 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove header information from responses sent by your website
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if ( $stepsString.Contains("9") )
{
$webConfigPath = "{0}\web.config" -f $site.physicalPath
[xml]$webConfigXML = Get-Content $webConfigPath
#Remove the X-Aspnet-Version HTTP header
$webConfigXML.configuration.'system.web'.httpRuntime.SetAttribute("enableVersionHeader","false")
$webConfigXML.Save($webConfigPath)
#Remove the X-Powered-By Http header
$psPath = "MACHINE/WEBROOT/APPHOST/{0}" -f $site.name
$filter = "system.webServer/httpProtocol/customHeaders"
Remove-WebConfigurationProperty -PSPath $psPath -Filter $filter -Name . -AtElement @{name='X-Powered-By'}
#Reminder to apply this one through implementation code
$caveat = @"
Missing change from the Sitecore recommendations regarding 'Remove the X-AspNetMvc-Version HTTP header'
-this is an implementation specific element that should come from source control etc
consider an HTTP Module (instead of Global.asax)
See the bottom of Akshay Sura's post for details:
http://www.akshaysura.com/2016/08/02/secure-sitecore-headers-are-a-headache-but-nothing-we-cannot-solve/
Do not forget this step!
"@
Write-Host $caveat -ForegroundColor DarkYellow
Write-Output "Step 9 completed - Remove header information from responses sent by your website"
}
else
{
Write-Output "Step 9 skipped - Not in stepsStrings variable"
}
Write-Host "Security hardening completed" -ForegroundColor Green