Add security for default WSMAN configuration - Remotely

Recently I was chatting with one of my friends  about Powershell remoting  and WSMAN . He was telling about how he got flagged by security for running WINRM on 5985 which is the default port on windows 2008r2 . I was like are you serious ? 5985 is not a standard port and his reply was this is the default and people know about it additionally they had windows firewall turned off using a domain policy. Over the conversation going back and forth I agreed to help him come up with some thing that would help him change it so that he keep security guys happy at the same time he get to enjoy the powershell remoting features which rides on top of winrm.

I started looking at it . That is when I understood there is a reason why security thinks it  not "secure". I dumped the winrm default config on my local machine running windows 2008 r2 

C:\Users\vbaby>winrm enumerate winrm/config/Listener
Listener
    Address = * -- All the configured addresses.
Transport = HTTP
    Port = 5985   -- Default port
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 192.168.0.4, 127.0.0.1, ::1 --- All IPs are listening for Winrm

Now  I am thinking the same as my friend we need to change this in prod environment.  All the machines in this scenario has 2 interfaces Customer facing, Admin. The security suggested measure was to lock WINRM on the admin interface on a non standard port and get the port opened through the Back end firewall.  I could come up with a script  in some time to do this as follows

gci WSMan:\localhost\Listener | Remove-Item -Recurse
$port="23001"
$IP=gwmi Win32_NetworkAdapterConfiguration | ? {$_.ipaddress -like '198*'} | select -expandproperty ipaddress
new-item -path WSMan:\localhost\Listener -Transport http -Address "ip:$IP" -Port 23001 -force

The first line removes the default listener, second line sets a non standard port, third line find the interface here all the admin interfaces started with 198. Fourth line created a listener  on the IP at the specified port.

Asked him to save it as <name>.ps1 and run it on all the machines he want to configure.  Send this off to him . That evening I receive an extension or the same request  " I need to run this on 200 + machines help me run it remotely".  

Looking at it I decided to use Psexec . Testing it Psexec was looking okay , only problem was I had to press enter twice after each execution , this was not looking good suddenly this is turning complex . Doing some online searches I found this https://www.leeholmes.com/blog/2007/10/02/using-powershell-and-psexec-to-invoke-expressions-on-remote-computers/ . Things were looking good after that . I saved the above script as remoting.ps1 on to  my utility server after that used a for loop to loop through my servers to test it. Here is the for loop

for /f %i in (\\utilityserver\servers\server.txt) do psexec \\%i /u domain\<user> /p <pass> cmd /c "echo .| powershell -file \\utilitserver\scripts\remoting.ps1"

PsExec v1.96 - Execute processes remotely
Copyright (C) 2001-2009 Mark Russinovich
Sysinternals - www.sysinternals.com

   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Listener

Name                      Type                 Keys
----                      ----                 ----
Listener_1226527951       Container            {Address=IP:192.168.0.10, Tran...

cmd exited on web9  with error code 0.

Now I have new listener on all may machines exactly the way I wanted on a particular port , on a particular IP all set up remotely . The only issue  is when I run remote power shell as invoke-command tries to 5985 by default.

 Invoke-Command -ComputerName web19 -ScriptBlock {gci cert:\localmachine\my}

[web19] Connecting to remote server failed with the following error message : The client cannot connect to the destination specified in the request. Veri
+ CategoryInfo : OpenError: (:) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionStateBroken

I have to specify the port now

Invoke-Command -ComputerName web19  -ScriptBlock {gci c:\ } -Port 23001

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          4/8/2010  12:08 PM            compaq
d----          4/8/2010  12:10 PM            CPQSYSTEM
d----          4/8/2010  12:08 PM            hp
d----          7/2/2010   7:57 AM            inetpub
d----          7/2/2010   8:00 AM            localbin
d----         7/13/2009   8:20 PM            PerfLogs
d-r--          8/8/2010  11:19 AM            Program Files
d-r--          8/8/2010  11:19 AM            Program Files (x86)

 

Looks like problem solved. Send this off to my friend , got  back a reply all good.

If you are interested to know how WSMAN works over a port when you even do not have IIS on a machine , try this from command prompt

netsh http show urlacl

Reserved URL            : https://+:23001/wsman/
   User: NT SERVICE\WinRM
       Listen: Yes
       Delegate: No
   User: NT SERVICE\Wecsvc
       Listen: Yes
       Delegate: No
       SDDL: D:(A;;GX;;;....)

You can see that the listener is created at the http.sys level.

In the next post we will look at having some fun with scheduled tasks and wevtutil.