jborean93 / pypsexec

Remote Windows execution like PsExec on Python
MIT License
119 stars 38 forks source link

Kerberos support on Windows #19

Closed goooroooX closed 4 years ago

goooroooX commented 5 years ago

Hi,

I'm implementing platform-independent code to manage Windows systems remotely (Active Directory). The sample code works just fine on Linux with KRB5 configured, but I'm getting following errors when executing on Windows box (same user account):

pypsexec.exceptions.SCMRException: Exception calling ROpenSCManagerW. Code: 5, Msg: ERROR_ACCESS_DENIED

I believe this is because "Windows implementation of the smbprotocol does not support Kerberos auth", as per readme.

Can you please clarify if there any plans to implement Kerberos support in smbprotocol for Windows?

Thank you!

goooroooX commented 5 years ago

I have discovered the issue: I can't connect to the host where python code is executed. Connecting any other remote Windows host is OK.

jborean93 commented 5 years ago

The smbprotocol library has recently added support for Kerberos on Windows hosts, you just need to make sure you have v0.2.0 installed.

Are you saying the error is when you use pypsexec against the localhost it is failing?

goooroooX commented 5 years ago

I'm using all the recent code. localhost is not working.

jborean93 commented 5 years ago

IIRC using localhost breaks Kerberos auth altogether so it will just fall back to NTLM auth. In any case that shouldn't be an issue though. Typically you get an access denied error from SCManager due to the LocalAccountTokenFilterPolicy not being set properly. But in the case of a domain account this shouldn't be affected. I'll have to play around with this a bit when I get some time to figure out what may be happening.

If you do find any more info that might be relevant please let me know.

goooroooX commented 5 years ago

I can provide you debug logs, but the issue is still the same: no 'specific' exception. Access denied while accessing service management on host. Let me know if you need any details. PS: thank you for this amazing stuff.

jborean93 commented 5 years ago

I don't think the debug logs would help here, I just need to try it out myself to see if I can replicate it. My prediction is that Windows treats a localhost auth differently than an actual network auth but I would need to prove that.

jborean93 commented 5 years ago

So I've been able to replicate this, it seems like when you connect over localhost it will just reuse the same token as the current process, in this case I was running under a standard console process. If I ran the exact same code as an admin process this worked just fine. This also only happens when pywin32 is installed so it is creating a token that is specially crafted to tell Windows to use the local token somehow. I'll have to see if there is a way around this issue as it isn't really that intuitive but at least it explains why this is happening.

Therefore as a workaround you will either have to:

jborean93 commented 4 years ago

I've thought about this a bit more and have decided to keep things the way they are today. If running on localhost there isn't a need really for remote connections over SMB so the credentials you use aren't important. Because of the nature of PAExec and how it works it requires admin privileges and so I don't think it's a stretch to say the script should already be run as an admin.

In any case you can make sure pywin32 is not installed and explicitly set the credentials but SSO won't ever work in this situation. If you need to run a process as another user then the credentials should just be supplied in the run_executable() function instead.

whitesec121 commented 4 years ago

Hi @jborean93 , I am having a similar issue. I am trying to connect to my windows host machine from the Linux guest (Installed in VMWARE Workstation) using the following piece of code and the error message is exactly as described by gooorooox. Could you let know what is possibly wrong?

`from pypsexec.client import Client import os import time import sys import paramiko

host = '192.168.0.32' user = '.\' passd = ''

c = Client(host, username=user, password=passd, encrypt=False,port=445) c.connect()

try: c.create_service() stdout = c.run_executable("cmd.exe", arguments="notepad",timeout_seconds=20) finally: c.cleanup() c.remove_service() c.disconnect()

output = [] output = stdout[0].decode("utf-8") print(output.split("\r\n")[1:3]) `