From 8d4350b8efbb554d610b0a8bd6203c5e0ba81ca9 Mon Sep 17 00:00:00 2001 From: yo Date: Sat, 6 Nov 2021 12:38:52 +0100 Subject: [PATCH 1/6] Add kerberos/domain user support --- winrm.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/winrm.go b/winrm.go index 2ea2bea..d03f2af 100644 --- a/winrm.go +++ b/winrm.go @@ -37,6 +37,7 @@ func main() { user string pass string ntlm bool + kerberos bool cmd string port int encoded bool @@ -52,6 +53,7 @@ func main() { flag.StringVar(&user, "username", "vagrant", "winrm admin username") flag.StringVar(&pass, "password", "vagrant", "winrm admin password") flag.BoolVar(&ntlm, "ntlm", false, "use use ntlm auth") + flag.BoolVar(&kerberos, "kerberos", false, "use kerberos auth. You need a TGT for this (obtained via kinit)") flag.BoolVar(&encoded, "encoded", false, "use base64 encoded password") flag.IntVar(&port, "port", 5985, "winrm port") flag.BoolVar(&https, "https", false, "use https") @@ -119,6 +121,10 @@ func main() { params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} } } + if kerberos { + params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberos{} } + } + client, err := winrm.NewClientWithParameters(endpoint, user, pass, params) check(err) From 6bda0ab7c54072611f8ca1cde915947f8c6db743 Mon Sep 17 00:00:00 2001 From: yo Date: Sat, 6 Nov 2021 12:39:18 +0100 Subject: [PATCH 2/6] Update README --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0f649f2..3801084 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a Go command-line executable to execute remote commands on Windows machines through the use of WinRM/WinRS. -_Note_: this tool doesn't support domain users (it doesn't support GSSAPI nor Kerberos). It's primary target is to execute remote commands on EC2 windows machines. +This tool support domain users via kerberos switch. For this to work, you will need a valid TGT (use kinit), a valid krb5.conf and your target must have a resolvable reverse entry. ## Contact @@ -13,8 +13,8 @@ _Note_: this tool doesn't support domain users (it doesn't support GSSAPI nor Ke ## Getting Started WinRM is available on Windows Server 2008 and up. This project natively supports basic authentication for local accounts, see the steps in the next section on how to prepare the remote Windows machine for this scenario. The authentication model is pluggable, see below for an example on using Negotiate/NTLM authentication (e.g. for connecting to vanilla Azure VMs). -### Preparing the remote Windows machine for Basic authentication -This project supports only basic authentication for local accounts (domain users are not supported). The remote windows system must be prepared for winrm: +### Preparing the remote Windows machine for Basic authentication (Not needed for Kerberos) +If you can not use kerberos, use basic authentication for local accounts. The remote windows system must be prepared for winrm: _For a PowerShell script to do what is described below in one go, check [Richard Downer's blog](http://www.frontiertown.co.uk/2011/12/overthere-control-windows-from-java/)_ @@ -60,6 +60,18 @@ Once built, you can run remote commands like this: ./winrm -hostname remote.domain.com -username "Administrator" -password "secret" "ipconfig /all" ``` +### kerberos authentication + +Ensure you have a ticket granting ticket before running winrm (use kinit/klist) +Also make sure remote.domain.com can be resolved forward and reverse + +```sh +./winrm -kerberos -hostname remote.domain.com "ipconfig /all" +``` +These options can be set as environment variables before running winrm : +KRB5_CONFIG points the kerberos config file. Default value is "/etc/krb5.conf" +KRB5CCNAME points the credential cache file. Default value is "/tmp/krb5cc_${UID}" + ## Docker ### Build image From 3d51c952234f995915f7b4e29eb12d40924eb9f1 Mon Sep 17 00:00:00 2001 From: yo Date: Sat, 6 Nov 2021 12:56:40 +0100 Subject: [PATCH 3/6] Update README --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3801084..ac0a67f 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,13 @@ Once built, you can run remote commands like this: ### kerberos authentication -Ensure you have a ticket granting ticket before running winrm (use kinit/klist) -Also make sure remote.domain.com can be resolved forward and reverse +Ensure you have a ticket granting ticket before running winrm (use kinit/klist). Also make sure remote.domain.com can be resolved forward and reverse ```sh ./winrm -kerberos -hostname remote.domain.com "ipconfig /all" ``` -These options can be set as environment variables before running winrm : -KRB5_CONFIG points the kerberos config file. Default value is "/etc/krb5.conf" +These options can be set as environment variables before running winrm : +KRB5_CONFIG points the kerberos config file. Default value is "/etc/krb5.conf" KRB5CCNAME points the credential cache file. Default value is "/tmp/krb5cc_${UID}" ## Docker From 6582ee37fb26c3268979795e5a22b7896fec8990 Mon Sep 17 00:00:00 2001 From: yo Date: Sat, 6 Nov 2021 16:32:58 +0100 Subject: [PATCH 4/6] Add -no-check-dns to come over misconfigured reverse with kerberos auth --- winrm.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/winrm.go b/winrm.go index d03f2af..cdd4597 100644 --- a/winrm.go +++ b/winrm.go @@ -33,20 +33,21 @@ import ( func main() { var ( - hostname string - user string - pass string - ntlm bool - kerberos bool - cmd string - port int - encoded bool - https bool - insecure bool - cacert string - gencert bool - certsize string - timeout string + hostname string + user string + pass string + ntlm bool + kerberos bool + nonscheck bool + cmd string + port int + encoded bool + https bool + insecure bool + cacert string + gencert bool + certsize string + timeout string ) flag.StringVar(&hostname, "hostname", "localhost", "winrm host") @@ -54,6 +55,7 @@ func main() { flag.StringVar(&pass, "password", "vagrant", "winrm admin password") flag.BoolVar(&ntlm, "ntlm", false, "use use ntlm auth") flag.BoolVar(&kerberos, "kerberos", false, "use kerberos auth. You need a TGT for this (obtained via kinit)") + flag.BoolVar(&nonscheck, "no-dns-check", false, "using kerberos auth, do not canonicalize hostname. Useful when reverse not available") flag.BoolVar(&encoded, "encoded", false, "use base64 encoded password") flag.IntVar(&port, "port", 5985, "winrm port") flag.BoolVar(&https, "https", false, "use https") @@ -122,7 +124,11 @@ func main() { } if kerberos { - params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberos{} } + if nonscheck { + params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberosWithNoCanonicalize{} } + } else { + params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberos{} } + } } client, err := winrm.NewClientWithParameters(endpoint, user, pass, params) From 925dd0db0534d7bbc292cf668fd11d07090ab2bf Mon Sep 17 00:00:00 2001 From: yo Date: Thu, 30 Dec 2021 10:27:46 +0100 Subject: [PATCH 5/6] Now support login/password kerberos auth (and still ccache with -ccache option) --- winrm.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/winrm.go b/winrm.go index cdd4597..af21d03 100644 --- a/winrm.go +++ b/winrm.go @@ -38,7 +38,8 @@ func main() { pass string ntlm bool kerberos bool - nonscheck bool + realm string + ccache string cmd string port int encoded bool @@ -54,8 +55,9 @@ func main() { flag.StringVar(&user, "username", "vagrant", "winrm admin username") flag.StringVar(&pass, "password", "vagrant", "winrm admin password") flag.BoolVar(&ntlm, "ntlm", false, "use use ntlm auth") - flag.BoolVar(&kerberos, "kerberos", false, "use kerberos auth. You need a TGT for this (obtained via kinit)") - flag.BoolVar(&nonscheck, "no-dns-check", false, "using kerberos auth, do not canonicalize hostname. Useful when reverse not available") + flag.BoolVar(&kerberos, "kerberos", false, "use kerberos auth") + flag.StringVar(&realm, "realm", "", "kerberos realm") + flag.StringVar(&ccache, "ccache", "", "kerberos credential cache file, usually /tmp/krb5cc_$UID") flag.BoolVar(&encoded, "encoded", false, "use base64 encoded password") flag.IntVar(&port, "port", 5985, "winrm port") flag.BoolVar(&https, "https", false, "use https") @@ -124,10 +126,23 @@ func main() { } if kerberos { - if nonscheck { - params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberosWithNoCanonicalize{} } - } else { - params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientKerberos{} } + proto := "http" + if https == true { + proto = "https" + } + + params.TransportDecorator = func() winrm.Transporter { + return &winrm.ClientKerberos{ + Username: user, + Password: pass, + Hostname: hostname, + Realm: realm, + Port: port, + Proto: proto, + KrbConf: "/etc/krb5.conf", + KrbCCache: ccache, + SPN: fmt.Sprintf("HTTP/%s", hostname), + } } } From 596db55ab2a590e4f4a9de83b58d5e08031494f5 Mon Sep 17 00:00:00 2001 From: yo000 <64189682+yo000@users.noreply.github.com> Date: Thu, 30 Dec 2021 10:34:26 +0100 Subject: [PATCH 6/6] Add kerberos usage --- README.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ac0a67f..8d4f891 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a Go command-line executable to execute remote commands on Windows machines through the use of WinRM/WinRS. -This tool support domain users via kerberos switch. For this to work, you will need a valid TGT (use kinit), a valid krb5.conf and your target must have a resolvable reverse entry. +This tool support domain users via kerberos switch. You can either use a login/password combination, or an existing credential cache (obtained via "kinit") ## Contact @@ -11,9 +11,9 @@ This tool support domain users via kerberos switch. For this to work, you will n ## Getting Started -WinRM is available on Windows Server 2008 and up. This project natively supports basic authentication for local accounts, see the steps in the next section on how to prepare the remote Windows machine for this scenario. The authentication model is pluggable, see below for an example on using Negotiate/NTLM authentication (e.g. for connecting to vanilla Azure VMs). +WinRM is available on Windows Server 2008 and up. This project natively supports basic authentication for local accounts, see the steps in the next section on how to prepare the remote Windows machine for this scenario. The authentication model is pluggable, see below for an example on using Negotiate/NTLM authentication (e.g. for connecting to vanilla Azure VMs) or kerberos (for domain accounts) -### Preparing the remote Windows machine for Basic authentication (Not needed for Kerberos) +### Preparing the remote Windows machine for Basic authentication If you can not use kerberos, use basic authentication for local accounts. The remote windows system must be prepared for winrm: _For a PowerShell script to do what is described below in one go, check [Richard Downer's blog](http://www.frontiertown.co.uk/2011/12/overthere-control-windows-from-java/)_ @@ -34,6 +34,16 @@ __N.B.:__ The `MaxMemoryPerShellMB` option has no effects on some Windows 2008R2 For more information on WinRM, please refer to the online documentation at Microsoft's DevCenter. +### Preparing the remote Windows machine for Kerberos authentication +The remote windows system must be prepared: + +On the remote host, a PowerShell prompt, using the __Run as Administrator__ option and paste in the following lines: + + winrm quickconfig + y + winrm set winrm/config/service '@{AllowUnencrypted="true"}' + winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}' + ### Building the winrm-cli executable You can build winrm-cli from source: @@ -62,14 +72,17 @@ Once built, you can run remote commands like this: ### kerberos authentication -Ensure you have a ticket granting ticket before running winrm (use kinit/klist). Also make sure remote.domain.com can be resolved forward and reverse +Either ensure you have a ticket granting ticket before running winrm (use kinit/klist), and run it with -ccache: + +```sh +./winrm -kerberos -ccache /tmp/krb5cc_10007 -hostname remote.domain.com "ipconfig /all" +``` + +Or if you want to user login/password : ```sh -./winrm -kerberos -hostname remote.domain.com "ipconfig /all" +./winrm -kerberos -username test -password s3cr3t -hostname remote.domain.com -realm DOMAIN.COM "ipconfig /all" ``` -These options can be set as environment variables before running winrm : -KRB5_CONFIG points the kerberos config file. Default value is "/etc/krb5.conf" -KRB5CCNAME points the credential cache file. Default value is "/tmp/krb5cc_${UID}" ## Docker