-
-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Support Kerberos Authentication #22
Comments
Hello @qichaozhao, Px uses winkerberos behind the scenes which should support your scenario. However, I have no way to try it out since I don't have such a setup. For starters, it would help to know if Px works as is for you. If it doesn't, please share the logs so that I can tell where exactly it is failing. You can run it with the --debug flag which will generate the logs. |
hey @genotrance, I have been messing about with this and looking at logs and it appears that winkerberos doesn't seem to support the microsoft implementation of kerberos (or at least, I couldn't get it working). Despite having valid kerberos tickets and passing GSSAPI auth method I still kept getting 407's. I hacked something together which works for my purposes using Go instead so please feel free to close this issue out. |
Thanks for the feedback. @behackett if you had any ideas here, will be appreciated. If you have a test script for winkerberos that can be tested outside the proxy scenario, will be great. |
If it helps, here is my hacked auth generator class: class NtlmMessageGenerator:
def __init__(self):
# if "winkerberos" in sys.modules:
status, self.ctx = winkerberos.authGSSClientInit("my.proxy.com")
self.get_response = self.get_response_wkb
def get_response_wkb(self, challenge=""):
dprint("winkerberos SSPI")
status = winkerberos.authGSSClientStep(self.ctx, '')
auth_req = winkerberos.authGSSClientResponse(self.ctx)
print(auth_req)
return auth_req and my hacked do_transaction code: def do_transaction(self):
dprint("Entering")
ipport = self.get_destination()
if ipport != None:
dprint("Skipping NTLM proxying")
resp, headers, body = self.do_socket(destination=ipport)
else:
# Check for NTLM auth
ntlm = NtlmMessageGenerator()
ntlm_resp = ntlm.get_response()
# if ntlm_resp == None:
# dprint("Bad NTLM response")
# return 503, None, None
resp, headers, body = self.do_socket({
"Proxy-Authorization": "Negotiate %s" % ntlm_resp
})
if resp == 407:
dprint("Auth required")
ntlm_challenge = ""
for header in headers:
if header[0] == "Proxy-Authenticate" and "Negotiate" in header[1]:
print(header)
# ntlm_challenge = header[1].split()[1]
ntlm_challenge = True
break
if ntlm_challenge:
dprint("Challenged")
ntlm_resp = ntlm.get_response(ntlm_challenge)
# if ntlm_resp == None:
# dprint("Bad NTLM response")
# return 503, None, None
resp, headers, body = self.do_socket({
"Proxy-Authorization": "Negotiate %s" % ntlm_resp
})
return resp, headers, body
else:
dprint("Didn't get challenge, not NTLM proxy")
elif resp > 400:
return resp, None, None
else:
dprint("No auth required")
return resp, headers, body Debug logs are as follows:
It's weird because it picks up the Kerberos ticket that I have active from my Windows Active Directory sign in but doesn't seem to generate the correct auth token that allows it to negotiate successfully with the proxy. Also as mentioned before since I have another working solution (https://github.com/qichaozhao/win-auth-proxy for anyone who stumbles upon this), this bugfix/enhancement is not a priority and more of a curiosity for me as to why it's not working as expected. :) |
I wrote WinKerberos specifically for Kerberos. I don't have an NTLM environment to test it any other way, and it's not clear to me how NTLM is supposed to work. One thing to try is passing mech_oid=winkerberos.GSS_MECH_OID_SPNEGO to authGSSClientInit. The default is winkerberos.GSS_MECH_OID_KRB5. |
I think the error is SEC_E_INVALID_TOKEN, which is documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa375507(v=vs.85).aspx
My previous recommendation stands, use GSS_MECH_OID_SPNEGO. |
@qichaozhao, I think you have mostly this figured out - Px is hard-coded to talk only NTLM so changing NTLM in the Proxy-Authorization and Proxy-Authenticate as you have to Negotiate will make it generic. I just tried this with my NTLM proxy and it worked. Can you try the same with mech_oid=winkerberos.GSS_MECH_OID_SPNEGO which you have removed in your code? |
@behackett, @genotrance, thank you! It turns out that that the Are you accepting PRs? I would be happy to tidy up my code and submit one to enable Negotiate style authentication for this proxy tool, perhaps through the use of an extra config line in the |
Thanks for all the work @qichaozhao. I've posted an updated version of Px which should work for you. Please verify that it works for you now. I've set the auth method to Negotiate throughout and it works for NTLM as well. I didn't have to add any extra config params either so hopefully it works across the board for everyone. I did have to remove support for pywin32 sspi since it wasn't working for Kerberos mode with my proxy. As such, there's no real value supporting both mechanisms and considering winkerberos works for both scenarios and for Python 3.4+, it makes more sense anyway. |
@genotrance , unfortunately this doesn't quite work - this is because of the For Kerberos authentication the target URL needs to be: The below change allows this to work for me. status, self.ctx = winkerberos.authGSSClientInit('HTTP@' + State.proxy_server[0][0], gssflags=0, mech_oid=winkerberos.GSS_MECH_OID_SPNEGO) |
It works with HTTP@ so I'll check this in shortly. Thanks for verifying. |
cool, cheers @genotrance! |
Hi genotrance,
Firstly thanks for building this awesome tool.
At my corp offices it seems by default Kerberos authentication is used and NTLM does not work for authenticating through the corporate proxy, is there any possibility you could work at adding authentication via using a Kerberos ticket cache?
I am happy to contribute if you can give me some guidance as to what needs to be done - I am familiar with Python but have no idea how these authentication mechanisms work.
The text was updated successfully, but these errors were encountered: