├── .gitignore
├── README.md
└── sawh.ps1
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX General
2 | .DS_Store
3 | .AppleDouble
4 | .LSOverride
5 | ._*
6 |
7 | # VIM Swap Files
8 | *.swp
9 |
10 | # Output files
11 | *.csv
12 | *.xml
13 | *.txt
14 | *.rtf
15 | *.xlsx
16 | *.json
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stand-Alone Windows Hardening (SAWH)
2 | SAWH is a PowerShell script to reduce the attack surface of Windows systems that are not attached to a Windows Active Directory Domain and do not require Windows services to function. Human-Machine Interface (MHI) systems within process environments often only require local access to interact with the system. These systems typically do not need to use services such as Network Browsing, IPv6, SMBv1, NetBIOS, and other Windows services to function properly. Therefore, to reduce the attack surface, many of these services can be disabled. This script provides a configurable way to modify the configuration of a stand-alone system without the need to configure, test, and install Security Templates. [Security Templates and Group Policy Objects (GPO)](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-compliance-toolkit-10), of course, are the BEST way to handle system hardening and SAWH should only be used as a stop-gap until your team can plan and test those technologies.
3 |
4 | # WARNING
5 |
6 | ***Use At Your Own Risk!!!! Do not run on production systems without testing.***
7 |
8 | Use at your own risk. Cutaway Security is not responsible for how this script affects your system, your network, your services, or your process. Users accept all responsibility for using this script in testing and production environments.
9 |
10 | ***Use At Your Own Risk!!!! Do not run on production systems without testing.***
11 |
12 | # Capabilities
13 | ## Running Modes
14 | SAWH provides three running modes.
15 |
16 | * 'check' - this performs a check of the system and the configuration of the script's actions.
17 | * 'disable' - this modifies the system to disable services and settings following the action verbs configured in the script.
18 | * 'rollback' - this modifies the system to rollback services and settings following the action verbs configured in the script. The rollback is not performed from a stored configuration for the system. The rollback resets the system to a normal default configuration by enabling the Windows services and network adapter settings. NOTE: except for SMBv1, you can roll this setting back manually.
19 |
20 | ## Configurations
21 | The following configurations can be updated within the script. Your team should review each and determine which should be enabled and which should be disabled. Then, they should test completely before using in production.
22 |
23 | * Interface Mode: modifies the mode of each network interface. Disabling puts the interfaces into 'Public' mode. Rolling back puts the interfaces into 'Private' mode.
24 | * NetBIOS: modifies the settings of each network interface. Disabling disables NetBIOS on each interface. Rolling back enables NetBIOS on each interface.
25 | * Firewall Rules: modifies the Windows Host-based Firewall with a rule named "Block Windows Services - SAWH" that controls TCP ports 135, 137, 139, and 445. Enabling creates the rule (if not present) and enables the rule. Rolling back does not remove the rule, it just disables it.
26 | * Bindings: Network interfaces have multiple configuration settings that can be controlled. The bindings setting controls the function of all. Each setting has its own setting.
27 | * IPv6: This setting controls the use of IPv6 on all interfaces. Disabling will disable IPv6 on all interfaces. Rolling back will enable IPv6 on all interfaces.
28 | * LLTP: This setting controls the use of Link-Layer Topology Discovery Mapper I/O Driver and the Microsoft LLDP Driver on all interfaces. Disabling will disable LLTP on all interfaces. Rolling back will enable LLTP on all interfaces.
29 | * Client: This setting controls the use of Client for Microsoft Networks and File and Printer Sharing for Microsoft Networks on all interfaces. Disabling will disable these services on all interfaces. Rolling back will enable these services on all interfaces.
30 | * NAMP: This setting controls the use of Microsoft Network Adapter Multiplexor Protocol on all interfaces. Disabling will disable NAMP on all interfaces. Rolling back will enable NAMP on all interfaces.
31 | * RDP: This setting controls the use of Terminal Services (RDP) on the system. Disabling will disable the RDP service in registry and also create a firewall rule name "Block RDP - SAWH" that blocks TCP 3389. Rolling back will enable the RDP service in registry and also disable the "Block RDP - SAWH" firewall without removing it.
32 | * This is the only rule that is disabled by default. This is because many organizations will require RDP to access these stand-alone systems. Update with care and testing.
33 | * SMB Configuration: This setting controls the configuration settings for SMB. Disabling will turn off SMB server and Workstation shares and will turn on and require SMB signing and encryption. Rolling back will reset the system to normal SMB default configuration which is to turn on SMB server and Workstation shares and disable SMB signing and encryption.
34 | * SMBv1: This setting controls the use of SMBv1. Disabling will disable SMBv1 on the system. ***Rolling back does nothing.*** You don't need SMBv1 for a stand-alone system. Don't enable it. Fire your vendor or integrator if they force you to enable it. If you really need it, you'll figure out how to enable it.
35 | * Seriously, you don't need SMBv1. Disabling it is extremely important.
36 | * Default Windows Apps: By default Windows 10 installs tens of additional applications not needed for ICS environment on the first user log in, such as BingWeather or XboxGameOverlay. Some of them are described on the [Mircrosoft website](https://docs.microsoft.com/en-us/windows/application-management/apps-in-windows-10). Disabling will uninstall most of the default Windows Apps. Rolling back will install them again (without recreating menu start tiles and windows bar shortcuts). The apps list can be modified per needs in the code.
37 |
38 | ## Considerations
39 | Check is safe. It makes no changes and there is a separate confirmation prompt when changes will be made to the system.
40 | Rolling back puts the system's state into an insecure default state. This script does not maintain the system's original configuration. You should run and store the check action in case you need to reconfigure the system to match the original state.
41 |
42 | # Usage
43 | Tell us about your experience on Twitter by tagging [@cutawaysecurity](https://twitter.com/cutawaysecurity) or, preferably, in this Github repo so others can help. Be sure to include your Windows version.
44 |
45 | ## Deploying via removable media
46 | * Prepare for rollback by backing up or taking a virtual snapshot of the system.
47 | * Download 'sawh.ps1' from this repository.
48 | * Modify any of the configurations verbs to change modifications to your desired configuration.
49 | * Copy the 'sawh.ps1' to a trusted removable media and place the file on the target system in the user's Downloads directory.
50 | * Start a PowerShell Terminal as Administrator. **This is required.**
51 | * Change to your downloads directory.
52 | * Allow scripts to run within the scope of this PowerShell process.
53 | ```powershell
54 | Set-ExecutionPolicy Bypass -Scope Process
55 | ```
56 | * Execute the script.
57 | ```powershell
58 | .\sawh.ps1
59 | ```
60 | * Follow the prompts.
61 | * Reboot your system.
62 | * Test your system's functionality. Rollback if necessary.
63 |
64 | ## Deploying via web server
65 | * Prepare for rollback by backing up or taking a virtual snapshot of the system.
66 | * Download 'sawh.ps1' from this repository.
67 | * Modify any of the configurations verbs to change modifications to your desired configuration.
68 | * Start a webserver on your system using Python.
69 | ```python
70 | python3 -m http.server 8181
71 | ```
72 | * Start a PowerShell Terminal on the target system as Administrator. **This is required.**
73 | * Change to the user's downloads directory.
74 | * Download the SAWH PowerShell script from the Python webserver.
75 | ```powershell
76 | (New-Object Net.WebClient).DownloadString('http://:8181/chaps/chaps.ps1') >.\sawh.ps1
77 | ```
78 | * Allow scripts to run within the scope of this PowerShell process.
79 | ```powershell
80 | Set-ExecutionPolicy Bypass -Scope Process
81 | ```
82 | * Execute the script.
83 | ```powershell
84 | .\sawh.ps1
85 | ```
86 | * Follow the prompts.
87 | * Reboot your system.
88 | * Test your system's functionality. Rollback if necessary.
89 |
90 | # Systems Tested
91 | Have you tested one successfully? Let us know.
92 |
93 | ## Windows Versions
94 | * Windows 10 Enterprise
95 | * 10.0.17763
96 | * Windows 2016 Server
97 | * 10.0.14393
98 | ## HMI / Software Solutions Tested
99 | * [BITS BACnet Site Auditor](https://www.bac-test.com/bacnet-site-auditor-download/)
100 |
101 | # Acknowledgements
102 | The following people and teams have assisted with the testing and / or direction of this project. CutSec sincerely appreciates their input and support.
103 |
104 | * Tom Liston [@tliston](https://twitter.com/tliston) - Bad Wolf Security, LLC
105 | * Ken Lassey, Cornell University
106 |
107 | # TODO
108 |
109 | * Log output to a local file as well as stdout.
110 | * Firewall rule to block UDP-based Windows service ports.
111 | * Disable other unnecessary Windows services.
112 | * Test user accounts and alert when there are no users that are not members of the Administrators group.
113 | * Determine if you can update system configuration to ensure new interfaces start with these settings?
114 | * Disable remote WMI and remote PowerShell.
115 | * Disable non-Administrators from starting CMD.exe and each version of PowerShell [using hash rules or path rules](https://docs.microsoft.com/en-us/windows-server/identity/software-restriction-policies/work-with-software-restriction-policies-rules).
116 | * Add startup/login/shutdown script to check and log configurations.
--------------------------------------------------------------------------------
/sawh.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | sawh.ps1 - Stand-Alone Windows Hardening (SAWH) is a PowerShell
3 | script to disable unnecessary Windows services on stand-alone Windows
4 | systems, such as Human Machine Interfaces and stand-alone workstations.
5 |
6 | WARNING: Do not run on production systems without testing.
7 | WARNING: Use at your own risk. Cutaway Security is not responsible for
8 | how this script affects your system, your network, your services,
9 | or your process. Users accept all responsibility for using this
10 | script in testing and production enviornments.
11 |
12 | Don't forget to run 'Set-ExecutionPolicy Bypass -Scope Process' to start.
13 | Be sure to reboot afterwards.
14 |
15 | Acknowledgements:
16 | Tom Liston (@tliston) - Bad Wolf Security, LLC
17 | Ken Lassey, Cornell University
18 | #>
19 |
20 | <#
21 | License:
22 | Copyright (c) 2021, Cutaway Security, Inc.
23 |
24 | sawh.ps1 is free software: you can redistribute it and/or modify
25 | it under the terms of the GNU General Public License as published by
26 | the Free Software Foundation, either version 3 of the License, or
27 | (at your option) any later version.
28 |
29 | sawh.ps1 is distributed in the hope that it will be useful,
30 | but WITHOUT ANY WARRANTY; without even the implied warranty of
31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 | GNU General Public License for more details.
33 | You should have received a copy of the GNU General Public License
34 | along with this program. If not, see .
35 | Point Of Contact: Don C. Weber
36 | #>
37 |
38 | ####################
39 | # Global Parameters
40 | ####################
41 |
42 | # Common Configuration Parameters
43 | $script_name = 'sawh.ps1'
44 | $sysversion = (Get-CimInstance Win32_OperatingSystem).version
45 | $show_warning = $true
46 | $warning = '
47 |
48 | ###################################################################################
49 | *** Use At Your Own Risk!!!! Do not run on production systems without testing. ***
50 |
51 | WARNING: Do not run on production systems without testing.
52 | WARNING: Use at your own risk. Cutaway Security is not responsible for
53 | how this script affects your system, your network, your services,
54 | or your process. Users accept all responsibility for using this
55 | script in testing and production enviornments.
56 |
57 | *** Use At Your Own Risk!!!! Do not run on production systems without testing. ***
58 | ###################################################################################
59 |
60 | '
61 | $start_state = $true # Enable / disable writing the system's state before beginning
62 | $completed_state = $true # Enable / disable writing the system's state after changes
63 |
64 | # Global Configuration verbs, modify these to disable modifications
65 | $inf_private_mode = $true # Network interfaces mode - true: 'Private' mode, false: 'Public' mode
66 | $disable_netbios = $true # Disable NetBIOS for all network interfaces
67 | $fw_rules = $true # Apply SAWH firewall rules
68 | $inf_bindings = $true # Change configuration of network interfaces
69 | $inf_bindings_ipv6 = $true # Disable IPv6 on all interfaces
70 | $inf_bindings_lltp = $true # Disable LLTP on all interfaces
71 | $inf_bindings_client = $true # Disable Client for Microsoft Networks and File and Printer Sharing for Microsoft Networks on all interfaces
72 | $inf_bindings_namp = $true # Disable NAMP on all interfaces
73 | $disable_rdp = $false # Disable rdp and block it on firewall. Not used by default because this may be required by some organizations
74 | $harden_smb = $true # Change configuration of SMB to more secure
75 | $disable_smbv1 = $true # Disable SMBv1, rolling back does nothing
76 | $uninstall_windows_apps = $true # Uninstall default Windows apps not needed for ICS
77 |
78 | # Global Action verbs, user input changes these
79 | $disable = $false
80 | $rollback = $false
81 | $check = $false
82 |
83 |
84 | ####################
85 | # Functions
86 | ####################
87 |
88 | ####################
89 | # Administration Functions
90 | ####################
91 |
92 | # Check for Administrator Role
93 | ####################
94 | function Get-AdminState {
95 | if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")){
96 | Write-Host "[!] You do not have Administrator rights. This script will not run correctly. Exiting"
97 | Exit
98 | } else {
99 | Write-Host "[*] Script running with Administrator rights."
100 | }
101 | }
102 | ####################
103 |
104 | # Confirm System Modifications
105 | ####################
106 | function Get-UserConfirmation {
107 | if ($show_warning){ Write-Host '*** Use At Your Own Risk!!!! Do not run on production systems without testing. ***' }
108 | $confirmation = Read-Host "Are you Sure You Want To Proceed? [n/y]"
109 | if ($confirmation -ne 'y') {
110 | Write-Host "[*] User selected to exit. Exiting..."
111 | Exit
112 | } else {
113 | Write-Host "[*] User selected to continue. Good luck..."
114 | }
115 | }
116 | ####################
117 |
118 | ####################
119 | # Action Functions
120 | ####################
121 |
122 | # Network interface modes
123 | ####################
124 | function Get-InterfaceModeState {
125 | Write-Host '[*] Checking Network interface modes'
126 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*'}) | ForEach-Object -Process {Get-NetConnectionProfile -InterfaceAlias $_.Name}
127 |
128 | # Let's give a little whitespace for readability
129 | Write-Host ''
130 | }
131 |
132 | function Set-InterfaceModeState {
133 |
134 | Param(
135 | # Enable means to change the setting to the default / insecure state.
136 | $Enable = $false
137 | )
138 |
139 | if ($inf_private_mode){
140 | # Check the physical interfaces, avoid loopbacks, and only act on interfaces that are up
141 | # NOTE: this will not change anything with intefaces with the status 'Disconnected'
142 | if (-NOT $Enable) {
143 | # Put all interfaces into 'Public' mode
144 | Write-Host '[*] Disable: Putting network interfaces into Public mode'
145 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}) | ForEach-Object -Process {Set-NetConnectionProfile -InterfaceAlias $_.Name -NetworkCategory Public}
146 | }else{
147 | # Put all interfaces into 'Private' mode
148 | Write-Host '[*] Enable / Rollback: Putting network interfaces into Private mode'
149 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}) | ForEach-Object -Process {Set-NetConnectionProfile -InterfaceAlias $_.Name -NetworkCategory Private}
150 | }
151 | }else{
152 | Write-Host '[!] Modification of network interfaces is disabled.'
153 | }
154 |
155 | # Let's give a little whitespace for readability
156 | Write-Host ''
157 | }
158 | ####################
159 |
160 | # NetBIOS
161 | ####################
162 | function Get-NetBIOSState{
163 | # Check the physical interfaces, avoid loopbacks, and only act on interfaces that are up
164 | # Get their interface GUID to query the specific registry key
165 | Write-Host "[*] Checking Interface NetBIOS States"
166 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}) | ForEach-Object -Process {
167 | $if_guid = $_.InterfaceGuid;
168 | $if_nb_setting = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\TCPIP_$if_guid).NetbiosOptions;
169 | $if_name = $_.Name;
170 | if ($if_nb_setting){$nb_config = 'Enabled'}else{$nb_config = 'Disabled'}
171 | Write-Host "[*] Interface $if_name : NetBIOS $nb_config [$if_nb_setting]";
172 | }
173 |
174 | # Let's give a little whitespace for readability
175 | Write-Host ''
176 | }
177 |
178 | function Set-NetBIOSState(){
179 |
180 | Param(
181 | # Enable means to change the setting to the default / insecure state.
182 | $Enable = $false
183 | )
184 |
185 | if ($disable_netbios){
186 | if (-NOT $Enable) {
187 | # Disable NetBIOS on active interfaces
188 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}) | ForEach-Object -Process {
189 | $if_guid = $_.InterfaceGuid;
190 | $if_nb_setting = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\TCPIP_$if_guid).NetbiosOptions;
191 | $if_name = $_.Name;
192 | if ($if_nb_setting){
193 | Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\TCPIP_$if_guid -Name NetBIOSoptions -Value 0
194 | Write-Host "[*] Interface $if_name : NetBIOS changed from $if_nb_setting to 0";
195 | }else{
196 | Write-Host "[*] Interface $if_name : NetBIOS Already Disabled [$if_nb_setting]";
197 | }
198 | }
199 | }else{
200 | # Enable NetBIOS on active interfaces
201 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}) | ForEach-Object -Process {
202 | $if_guid = $_.InterfaceGuid;
203 | $if_nb_setting = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\TCPIP_$if_guid).NetbiosOptions;
204 | $if_name = $_.Name;
205 | if ($if_nb_setting){
206 | Write-Host "[*] Interface $if_name : NetBIOS Already Enabled [$if_nb_setting]";
207 | }else{
208 | Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\TCPIP_$if_guid -Name NetBIOSoptions -Value 2
209 | Write-Host "[*] Interface $if_name : NetBIOS changed from $if_nb_setting to 2";
210 | }
211 | }
212 | }
213 | }else{
214 | Write-Host '[!] Modification of network interface NetBIOS settings is disabled.'
215 | }
216 |
217 | # Let's give a little whitespace for readability
218 | Write-Host ''
219 | }
220 | ####################
221 |
222 | # Firewall Rules
223 | ####################
224 | function Get-SAWHFWRulesState(){
225 | # Check for the 'Block Windows Services - SAWH'
226 | # Get their interface GUID to query the specific registry key
227 | Write-Host '[*] Checking for Block Windows Services - SAWH rule using Windows Firewall'
228 | $check_sw_fw_rule = Get-NetFirewallRule -DisplayName "Block Windows Services - SAWH" -ErrorAction SilentlyContinue
229 | if ($check_sw_fw_rule){
230 | if (($check_sw_fw_rule).Enable){
231 | Write-Host '[*] Block Windows Services - SAWH rule enabled.'
232 | }else{
233 | Write-Host '[*] Block Windows Services - SAWH rule disabled.'
234 | }
235 | Write-Host '[*] Windows Services - SAWH rule configuration'
236 | $check_sw_fw_rule
237 | Write-Host '[*] Windows Services - SAWH rule port settings'
238 | $check_sw_fw_rule | Get-NetFirewallPortFilter
239 | }else{
240 | Write-Host '[*] Block Windows Services - SAWH rule not configured on this system'
241 | }
242 |
243 | # Let's give a little whitespace for readability
244 | Write-Host ''
245 | }
246 |
247 | function Set-SAWHFWRulesState(){
248 |
249 | Param(
250 | # Enable means to change the setting to the default / insecure state.
251 | $Enable = $false
252 | )
253 |
254 | if ($fw_rules){
255 | $check_sw_fw_rule = Get-NetFirewallRule -DisplayName "Block Windows Services - SAWH" -ErrorAction SilentlyContinue
256 | if (-NOT $Enable) {
257 | # Disable Windows services by adding firewall rule
258 | if ($check_sw_fw_rule){
259 | if (($check_sw_fw_rule).Enable){
260 | Write-Host '[*] Block Windows Services - SAWH rule already enabled.'
261 | }else{
262 | Set-NetFirewallRule -DisplayName "Block Windows Services - SAWH" -Enabled True
263 | Write-Host '[*] Block Windows Services - SAWH rule enabled.'
264 | }
265 | }else{
266 | # TODO: Add UDP Firewall Rule
267 | New-NetFirewallRule -DisplayName "Block Windows Services - SAWH" -Direction Inbound -LocalPort 135,137,139,445 -Protocol TCP -Action Block
268 | }
269 | }else{
270 | # Enable Windows services by disabling firewall rule
271 | if ($check_sw_fw_rule){
272 | if (($check_sw_fw_rule).Enable){
273 | Set-NetFirewallRule -DisplayName "Block Windows Services - SAWH" -Enabled False
274 | Write-Host '[*] Block Windows Services - SAWH rule disabled.'
275 | }else{
276 | Write-Host '[*] Block Windows Services - SAWH rule already disabled.'
277 | }
278 | }else{
279 | Write-Host '[*] Block Windows Services - SAWH rule not configured on this system'
280 | }
281 | }
282 | }else{
283 | Write-Host '[!] Modification of firewall rules is disabled.'
284 | }
285 |
286 | # Let's give a little whitespace for readability
287 | Write-Host ''
288 | }
289 | ####################
290 |
291 | # Interface inf_bindings
292 | ####################
293 | function Get-NetInfBindingsState(){
294 | ####################
295 | # Check Network Adapter inf_bindings
296 | ####################
297 | Write-Host '[*] Checking Network Adapter inf_bindings'
298 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}).InterfaceAlias | ForEach-Object -Process {Get-NetAdapterBinding -InterfaceAlias $_}
299 |
300 | # Let's give a little whitespace for readability
301 | Write-Host ''
302 | }
303 |
304 | function Set-NetInfBindingsState(){
305 |
306 | Param(
307 | # Enable means to change the setting to the default / insecure state.
308 | $Enable = $false
309 | )
310 |
311 | if ($inf_bindings){
312 | if (-NOT $Enable) {
313 | # Disable selected inf_bindings
314 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}).InterfaceAlias | ForEach-Object -Process {
315 | if ($inf_bindings_ipv6) {
316 | # Disable IPv6
317 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_tcpip6
318 | }
319 | if ($inf_bindings_lltp) {
320 | # Disable Link-Layer Topology Discovery Mapper I/O Driver
321 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_lltdio
322 | # Disable Microsoft LLDP protocol Driver
323 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_lldp
324 | }
325 | if ($inf_bindings_client) {
326 | # Disable Client for Microsoft Networks
327 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_msclient
328 | # Disable File and Printer Sharing for Microsoft Networks
329 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_server
330 | }
331 | if ($inf_bindings_namp) {
332 | # Disable Microsoft Network Adapter Multiplexor Protocol
333 | Disable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_implat
334 | }
335 | }
336 | }else{
337 | # Enable selected inf_bindings
338 | (Get-NetAdapter -Physical | Where-Object {$_.Name -NotLike '*Loopback*' -And $_.Status -eq 'Up'}).InterfaceAlias | ForEach-Object -Process {
339 | if ($inf_bindings_ipv6) {
340 | # Disable IPv6
341 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_tcpip6
342 | }
343 | if ($inf_bindings_lltp) {
344 | # Disable Link-Layer Topology Discovery Mapper I/O Driver
345 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_lltdio
346 | # Disable Microsoft LLDP protocol Driver
347 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_lldp
348 | }
349 | if ($inf_bindings_client) {
350 | # Disable Client for Microsoft Networks
351 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_msclient
352 | # Disable File and Printer Sharing for Microsoft Networks
353 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_server
354 | }
355 | if ($inf_bindings_namp) {
356 | # Disable Microsoft Network Adapter Multiplexor Protocol
357 | Enable-NetAdapterBinding -InterfaceAlias $_ -ComponentID ms_implat
358 | }
359 | }
360 | }
361 | }else{
362 | Write-Host '[!] Modification of interface inf_bindings is disabled.'
363 | }
364 |
365 | # Let's give a little whitespace for readability
366 | Write-Host ''
367 | }
368 | ####################
369 |
370 | # Terminal Services (RDP)
371 | ####################
372 | function Get-TerminalServicesState(){
373 | # Check for RDP Registry Setting
374 | Write-Host '[*] Checking RDP Registry Configuration'
375 | if ((Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections").fDenyTSConnections){
376 | Write-Host '[*] RDP is Disabled'
377 | }else{
378 | Write-Host '[*] RDP is Enabled'
379 | }
380 |
381 | # Check for the 'Block RDP - SAWH'
382 | # Get their interface GUID to query the specific registry key
383 | Write-Host '[*] Check for Block RDP - SAWH rule using Windows Firewall'
384 | $check_rdp_fw_rule = Get-NetFirewallRule -DisplayName "Block RDP - SAWH" -ErrorAction SilentlyContinue
385 | if ($check_rdp_fw_rule){
386 | if (($check_rdp_fw_rule).Enable){
387 | Write-Host '[*] Block RDP - SAWH rule enabled.'
388 | }else{
389 | Write-Host '[*] Block RDP - SAWH rule disabled.'
390 | }
391 | Write-Host '[*] RDP - SAWH rule configuration'
392 | $check_rdp_fw_rule
393 | Write-Host '[*] RDP - SAWH rule port settings'
394 | $check_rdp_fw_rule | Get-NetFirewallPortFilter
395 | }else{
396 | '[*] Block RDP - SAWH rule not configured on this system'
397 | }
398 |
399 | # Let's give a little whitespace for readability
400 | Write-Host ''
401 | }
402 |
403 | function Set-TerminalServicesState(){
404 |
405 | Param(
406 | # Enable means to change the setting to the default / insecure state.
407 | $Enable = $false
408 | )
409 |
410 | if ($disable_rdp){
411 | $disable_rdp_setting = Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections"
412 | $check_rdp_fw_rule = Get-NetFirewallRule -DisplayName "Block RDP - SAWH" -ErrorAction SilentlyContinue
413 | if (-NOT $Enable) {
414 | # Disable RDP in registry
415 | if ($disable_rdp_setting.fDenyTSConnections){
416 | Write-Host '[*] RDP was already disabled'
417 | }else{
418 | Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value 1
419 | Write-Host '[*] RDP was disabled'
420 | }
421 | # Disable RDP in Firewall
422 | if ($check_rdp_fw_rule){
423 | if (($check_rdp_fw_rule).Enable){
424 | Write-Host '[*] Block RDP - SAWH rule already enabled.'
425 | }else{
426 | Set-NetFirewallRule -DisplayName "Block RDP - SAWH" -Enabled True
427 | Write-Host '[*] Block RDP - SAWH rule enabled.'
428 | }
429 | }else{
430 | # TODO: Add UDP Firewall Rule
431 | New-NetFirewallRule -DisplayName "Block RDP - SAWH" -Direction Inbound -LocalPort 3389 -Protocol TCP -Action Block
432 | }
433 | }else{
434 | # Enable RDP in registry
435 | if ($disable_rdp_setting.fDenyTSConnections){
436 | Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value 0
437 | Write-Host '[*] RDP was enabled'
438 | }else{
439 | Write-Host '[*] RDP was already enabled'
440 | }
441 | # Enable RDP by disabling firewall rule
442 | if ($check_rdp_fw_rule){
443 | if (($check_rdp_fw_rule).Enable){
444 | Set-NetFirewallRule -DisplayName "Block RDP - SAWH" -Enabled False
445 | Write-Host '[*] Block RDP - SAWH rule disabled.'
446 | }else{
447 | Write-Host '[*] Block RDP - SAWH rule already disabled.'
448 | }
449 | }else{
450 | Write-Host '[*] Block RDP - SAWH rule not configured on this system'
451 | }
452 | }
453 | }else{
454 | Write-Host '[!] Modification of Terminal Services (RDP) is disabled.'
455 | }
456 |
457 | # Let's give a little whitespace for readability
458 | Write-Host ''
459 | }
460 | ####################
461 |
462 | # Service Message Bus (SMB) Hardening
463 | ####################
464 | function Get-SMBConfigState(){
465 |
466 | ####################
467 | # Check SMB Configuration
468 | ####################
469 | Write-Host '[*] Checking SMB Configuration'
470 | Write-Host "[*] SMB configuration is currently: "
471 | Get-SmbServerConfiguration
472 |
473 | # Let's give a little whitespace for readability
474 | Write-Host ''
475 | }
476 |
477 | function Set-SMBConfigState(){
478 |
479 | Param(
480 | # Enable means to change the setting to the default / insecure state.
481 | $Enable = $false
482 | )
483 |
484 | ####################
485 | # Disable SMBv1 - This should be last because of reboot prompt
486 | ####################
487 | if ($harden_smb){
488 | if (-NOT $Enable) {
489 | Write-Host '[*] Hardening SMB configuration settings.'
490 | Set-SmbServerConfiguration -AutoShareServer $false -AutoShareWorkstation $false -RequireSecuritySignature $true -EnableSecuritySignature $true -EncryptData $true -Confirm:$false
491 | }else{
492 | Write-Host '[*] Setting SMB service back to standard default configuration.'
493 | Set-SmbServerConfiguration -AutoShareServer $true -AutoShareWorkstation $true -RequireSecuritySignature $false -EnableSecuritySignature $false -EncryptData $false -Confirm:$false
494 | }
495 | }
496 |
497 | # Let's give a little whitespace for readability
498 | Write-Host ''
499 | }
500 |
501 | # Service Message Bus version 1 (SMBv1)
502 | ####################
503 | function Get-SMBv1State(){
504 |
505 | ####################
506 | # Check SMBv1
507 | ####################
508 | Write-Host '[*] Checking SMBv1 Configuration'
509 | $smb_state = (Get-WindowsOptionalFeature -Online -FeatureName smb1protocol).State
510 | Write-Host "[*] SMBv1 is currently: $smb_state"
511 |
512 | # Let's give a little whitespace for readability
513 | Write-Host ''
514 | }
515 |
516 | function Set-SMBv1State(){
517 |
518 | Param(
519 | # Enable means to change the setting to the default / insecure state.
520 | $Enable = $false
521 | )
522 |
523 | ####################
524 | # Disable SMBv1 - This should be last because of reboot prompt
525 | ####################
526 | if ($disable_smbv1){
527 | $smb_state = (Get-WindowsOptionalFeature -Online -FeatureName smb1protocol).State
528 | if (-NOT $Enable) {
529 | if ($smb_state -eq 'Enabled'){
530 | Write-Host '[*] Disabling SMBv1 - requires reboot'
531 | Disable-WindowsOptionalFeature -Online -FeatureName smb1protocol
532 | }else{
533 | Write-Host '[*] SMBv1 already disabled.'
534 | }
535 | }else{
536 | Write-Host '[*] We are not going to enable SMBv1. You do not need it. Do it yourself.'
537 | # Enable-WindowsOptionalFeature -Online -FeatureName smb1protocol
538 | }
539 | }
540 |
541 | # Let's give a little whitespace for readability
542 | Write-Host ''
543 | }
544 |
545 | ####################
546 |
547 | # Default Windows apps
548 | ####################
549 | function Get-DefaultWindowsApps(){
550 | Write-Host '[*] Getting list of installed Windows apps'
551 | Get-AppxPackage | Format-Table Name
552 | # Uncomment to get list of apps that will be installed for future users
553 | #Get-AppxProvisionedPackage -Online | Format-Table DisplayName, PackageName
554 | }
555 |
556 | function Set-DefaultWindowsApps(){
557 | Param(
558 | # Enable means to change the setting to the default / insecure state.
559 | $Enable = $false
560 | )
561 |
562 | #List of default windows apps to uninstall
563 | $default_windows_apps = (
564 | "Microsoft.BingWeather",
565 | "Microsoft.BingNews",
566 | "Microsoft.BingFinance",
567 | "Microsoft.BingSports",
568 | "Microsoft.BingTranslator",
569 | "Microsoft.Print3D",
570 | "Microsoft.3DBuilder",
571 | "Microsoft.Microsoft3DViewer",
572 | "Microsoft.DesktopAppInstaller",
573 | "Microsoft.GetHelp",
574 | "Microsoft.Getstarted",
575 | "Microsoft.Messaging",
576 | "Microsoft.MicrosoftOfficeHub",
577 | "Microsoft.MicrosoftSolitaireCollection",
578 | "Microsoft.MixedReality.Portal",
579 | "Microsoft.OneConnect",
580 | "Microsoft.People",
581 | "Microsoft.SkypeApp",
582 | "Microsoft.StorePurchaseApp",
583 | "Microsoft.Wallet",
584 | "Microsoft.WindowsMaps",
585 | "Microsoft.WindowsStore",
586 | "Microsoft.Xbox.TCUI",
587 | "Microsoft.XboxApp",
588 | "Microsoft.XboxGameOverlay",
589 | "Microsoft.XboxGamingOverlay",
590 | "Microsoft.XboxIdentityProvider",
591 | "Microsoft.XboxSpeechToTextOverlay",
592 | "Microsoft.YourPhone",
593 | "Microsoft.ZuneMusic",
594 | "Microsoft.ZuneVideo",
595 | "Microsoft.Whiteboard",
596 | "Microsoft.WindowsSoundRecorder",
597 | "microsoft.windowscommunicationsapps",
598 | "Microsoft.RemoteDesktop", #this doesn't block rdp, its just modern Windows app
599 | "Microsoft.NetworkSpeedTest",
600 | "Microsoft.Office.Sway"
601 | )
602 |
603 | if ($uninstall_windows_apps){
604 | if (-NOT $Enable) {
605 | Write-Host '[*] Uninstalling selected default Windows apps for all current users.'
606 | foreach($app in $default_windows_apps){
607 | Write-host "Uninstalling $app"
608 | Get-AppxPackage -Name $app -AllUsers | Remove-AppxPackage
609 | # Uncomment to remove it completely, makes it impossible to install
610 | #Get-AppxProvisionedPackage -Online | Where-Object {$_.DisplayName -eq $app} | Remove-AppxProvisionedPackage -Online
611 | Write-Host '[*] Selected default Windows apps uninstalled.'
612 | }
613 | }
614 | else{
615 | Write-Host '[*] Installing selected default Windows apps.'
616 | foreach($app in $default_windows_apps){
617 | Write-host "Installing $app"
618 | Get-AppxPackage -AllUsers $app | ForEach-Object {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}
619 | Write-Host '[*] Selected default Windows apps installed - shortcuts need to be restored manually.'
620 | }
621 | }
622 | }
623 | }
624 |
625 | ####################
626 | # Print Functions
627 | ####################
628 |
629 |
630 | # Print program beginning message
631 | ####################
632 | function Write-ProgStart {
633 | if ($show_warning){ Write-Host "$warning" }
634 | Write-Host "[*] Started Date/Time: $(get-date -format yyyyMMddTHHmmssffzz)"
635 | Write-Host "[*] Running on Windows: $sysversion"
636 | Write-Host "[*] $script_name is about to start. Run the following Nmap scan (from a seperate system) and check current statue before proceeding:"
637 | Write-Host '[*] sudo nmap -sT -p 135,137,139,445,3389 '
638 | }
639 | ####################
640 |
641 | # Print program completed message
642 | ####################
643 | function Write-ProgComplete {
644 | Write-Host "[*] Completed Date/Time: $(get-date -format yyyyMMddTHHmmssffzz)"
645 | Write-Host "[*] $script_name has completed. Run the following Nmap scan (from a seperate system) and check the results:"
646 | Write-Host '[*] sudo nmap -sT -p 135,137,139,445,3389 '
647 | Write-Host '[*] Do not forget to reboot before testing.'
648 | }
649 | ####################
650 |
651 | # Print configuration information
652 | ####################
653 | function Write-SAWHConfig {
654 | Write-Host ""
655 | Write-Host "################################"
656 | Write-Host "[*] SAWH Configuration Settings"
657 | Write-Host "################################"
658 | Write-Host "[*] Running on Windows: $sysversion"
659 | Write-Host "[*] Modifying network interface mode is set to: $inf_private_mode"
660 | Write-Host "[*] Modifying NetBIOS is set to: $disable_netbios"
661 | Write-Host "[*] Modifying Firewall Rules is set to: $fw_rules"
662 | Write-Host "[*] Modifying Network Adapter inf_bindings is set to: $inf_bindings"
663 | Write-Host " [*] Modifying Network Adapter IPv6 Binding is set to: $inf_bindings_ipv6"
664 | Write-Host " [*] Modifying Network Adapter LLTP inf_bindings is set to: $inf_bindings_lltp"
665 | Write-Host " [*] Modifying Network Adapter Client / Server inf_bindings is set to: $inf_bindings_client"
666 | Write-Host " [*] Modifying Network Adapter Multiplexor Binding is set to: $inf_bindings_namp"
667 | Write-Host "[*] Modifying Terminal Services (RDP) is set to: $disable_rdp"
668 | Write-Host "[*] Modifying SMB Configuration is set to: $harden_smb"
669 | Write-Host "[*] Modifying SMBv1 is set to: $disable_smbv1"
670 | Write-Host "[*] Uninstalling default Windows Apps is set to: $uninstall_windows_apps"
671 | Write-Host "################################"
672 | Write-Host ""
673 | }
674 | ####################
675 |
676 | # Print System State
677 | ####################
678 | function Write-SystemState {
679 | Get-InterfaceModeState
680 | Get-NetBIOSState
681 | Get-SAWHFWRulesState
682 | Get-NetInfBindingsState
683 | Get-TerminalServicesState
684 | Get-SMBConfigState
685 | Get-SMBv1State
686 | Get-DefaultWindowsApps
687 | }
688 | ####################
689 |
690 |
691 | ####################
692 | # Main
693 | ####################
694 | Get-AdminState
695 | Write-ProgStart
696 |
697 | # Determine what user wants to do
698 | ####################
699 | $action = Read-Host "Do you want to check, disable, or rollback Windows services? [check/disable/rollback]"
700 | # Set user input.
701 | if ($action -eq 'check') {
702 | $check = $true
703 | }
704 | if ($action -eq 'disable') {
705 | $disable = $true
706 | }
707 | if ($action -eq 'rollback') {
708 | $rollback = $true
709 | }
710 | # Check user input. Fail if it isn't exactly what we expected
711 | if ($rollback -eq $false -And $disable -eq $false -And $check -eq $false){
712 | Write-Host "[!] User did not select a valid action. Exiting..."
713 | Exit
714 | }
715 |
716 | # Run check function
717 | ####################
718 | if ($check){
719 | Write-SAWHConfig
720 | Write-SystemState
721 | Exit
722 | }
723 |
724 | # Run action functions
725 | ####################
726 | # Write state before we start?
727 | if ($start_state) { Write-SystemState }
728 |
729 | # Run disable function
730 | ####################
731 | if ($disable){
732 | # Get user confirmation before proceeding
733 | Write-Host "[*] SAWH Disable Function"
734 | Get-UserConfirmation
735 |
736 | Set-InterfaceModeState
737 | Set-NetBIOSState
738 | Set-SAWHFWRulesState
739 | Set-NetInfBindingsState
740 | Set-TerminalServicesState
741 | Set-SMBConfigState
742 | Set-SMBv1State
743 | Set-DefaultWindowsApps
744 | }
745 |
746 | # Run rollback function
747 | ####################
748 | if ($rollback){
749 | # Get user confirmation before proceeding
750 | Write-Host "[*] SAWH Rollback Function"
751 | Get-UserConfirmation
752 |
753 | Set-InterfaceModeState -Enable $true
754 | Set-NetBIOSState -Enable $true
755 | Set-SAWHFWRulesState -Enable $true
756 | Set-NetInfBindingsState -Enable $true
757 | Set-TerminalServicesState -Enable $true
758 | Set-SMBConfigState -Enable $true
759 | Set-SMBv1State -Enable $true
760 | Set-DefaultWindowsApps -Enable $true
761 |
762 | }
763 |
764 | # Write state after completion?
765 | if ($completed_state) { Write-SystemState }
766 |
767 | # All done, say goodbye
768 | Write-ProgComplete
769 |
--------------------------------------------------------------------------------