Closed maaaaz closed 4 years ago
And by the way, there's also the error with GetNPUsers.py
:
$ python GetNPUsers.py adyolo.swag/test:<cred>@192.168.11.144 -dc-ip 192.168.11.144 -outputfile lol -debug
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies
[+] Connecting to 192.168.11.144, port 389, SSL False
[*] Cannot authenticate test, getting its TGT
[+] Trying to connect to KDC at 192.168.11.144
$krb5asrep$23$test@ADYOLO.SWAG:5ca3e0c1cf31bc743cc4027b0774552b$<hash>
Hmm.. I have no clue what that could be @maaaaz .
I'm assuming those creds are working well when using smbclient.py
or other tools that do not touch LDAP.
Did you try other LDAP tools, is ldapsearch
working with those creds? Try using -k
on those scripts, maybe NTLM is disabled?
Yes, these credz work with common LDAP browser such as Sysinternal ADExplorer
, my DC or domain does not have anything specific (2 or 3 users, nothing else configured).
It seems to a be common issue when connecting to an AD (https://stackoverflow.com/questions/23426739/connecting-python-to-ldap-server-using-python-ldap-getting-desc-invalid-cre) but I can't find how to specify OPT_REFERRALS
to 0 (or equivalent) in these modules current code...
Hmm.. interesting @maaaaz .
Is there any chance to get a PCAP of ADExplorer
or similar working (it should be ldap
not ldaps
) so I can see the specific options added and where?.. Looks like we don't have support for that at the moment.
Sure, I attached 2 pcaps :
domain\login
might be misunderstood by the DC..144 is the DC server, .154 is the client (not domain-joined).
Do you know if some people did manage to make GetADUsers.py
work on a real environment ? From a domain-joined machine ?
Cheers amigo !
Thanks @maaaaz
At first sight I'm not seeing much difference actually.. just the successful one then encrypting the contents..
Have you tried forcing the connection to ldaps
instead? Try changing this line.
Another thing that could happen is the server enforcing encryption/signing, although I never played with that in the context of LDAP.
I tried by changing ldap://
to ldaps://
here, unsuccessfully:
$ python GetADUsers2.py adyolo.swag/test:<cred>@192.168.11.144 -dc-ip 192.168.11.144 -debug
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies
[+] Connecting to 192.168.11.144, port 636, SSL True
Traceback (most recent call last):
File "GetADUsers2.py", line 240, in <module>
executer.run()
File "GetADUsers2.py", line 131, in run
ldapConnection = ldap.LDAPConnection('ldaps://%s'%self.__target, self.baseDN, self.__kdcHost)
File "build\bdist.win32\egg\impacket\ldap\ldap.py", line 118, in __init__
self._socket.do_handshake()
File "Z:\Partage\impacket_fork\venvimpacketwinnew\lib\site-packages\OpenSSL\SSL.py", line 1907, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "Z:\Partage\impacket_fork\venvimpacketwinnew\lib\site-packages\OpenSSL\SSL.py", line 1632, in _raise_ssl_error
raise SysCallError(-1, "Unexpected EOF")
SysCallError: (-1, 'Unexpected EOF')
(-1, 'Unexpected EOF')
On the server-side, I only see a SSL/TLS ClientHello
attempt and then nothing:
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 97
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 93
Version: TLS 1.0 (0x0301)
Random: ad9e2c711c07de673902ea5e34955895cd3544a30f311f85...
GMT Unix Time: Apr 21, 2062 06:53:53.000000000 Romance Standard Time
Random Bytes: 1c07de673902ea5e34955895cd3544a30f311f8575e895e7...
Session ID Length: 0
Cipher Suites Length: 18
Cipher Suites (9 suites)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Compression Methods Length: 1
Compression Methods (1 method)
Compression Method: null (0)
Extensions Length: 34
Extension: ec_point_formats (len=4)
Type: ec_point_formats (11)
Length: 4
EC point formats Length: 3
Elliptic curves point formats (3)
EC point format: uncompressed (0)
EC point format: ansiX962_compressed_prime (1)
EC point format: ansiX962_compressed_char2 (2)
Extension: supported_groups (len=10)
Type: supported_groups (10)
Length: 10
Supported Groups List Length: 8
Supported Groups (4 groups)
Supported Group: x25519 (0x001d)
Supported Group: secp256r1 (0x0017)
Supported Group: secp521r1 (0x0019)
Supported Group: secp384r1 (0x0018)
Extension: SessionTicket TLS (len=0)
Type: SessionTicket TLS (35)
Length: 0
Data (0 bytes)
Extension: encrypt_then_mac (len=0)
Type: encrypt_then_mac (22)
Length: 0
Extension: extended_master_secret (len=0)
Type: extended_master_secret (23)
Length: 0
I also think that it may have to do with encryption/signing but have no clue how to dig deeper. It would be nice to have a pcap of a working connection and then diff the results.
So I've been running into the same issue, on what sounds like a very similar environment (2012R2 DC, in a very simple lab, Kali Linux client). Although I did find a work-around, I haven't been able to pinpoint the exact issue.
I found running GetADUsers.py lab.local/pat@192.168.56.10
or GetADUsers.py lab.local/pat@pdc.lab.local
would fail, referencing the same AcceptSecurityContext errors as OP (without even prompting for a password).
However, running GetADUsers.py lab.local/pat -all
or GetADUsers.py lab.local/pat -dc-ip 192.168.56.10 -all
would return users, after prompting for a password.
The bit that confuses me though, is that I couldn't spot any differences in the Wireshark captures/initial LDAP handshake between failure and success...
The old thread but is still open. It seems that the problem was due to the extra @ sign that was always appended to the end of the target option string, so it was parsed incorrectly (https://github.com/SecureAuthCorp/impacket/blame/96b522884f31f68cfff6cda24c2c30827b3b35e8/examples/GetADUsers.py#L225-L231)
the following
python GetUserSPNs.py adyolo.swag/test:<cred>@192.168.11.144 -dc-ip 192.168.11.144 -debug
resulted in
options.target = 'adyolo.swag/test:<cred>@192.168.11.144'
targetParam = 'adyolo.swag/test:<cred>@192.168.11.144@'
password = '<cred>@192.168.11.144'
address = ''
@rmaksimov, wow so it would really come only from a parsing error ? nice finding ! Obvious things are sometimes not that obvious.
@rmaksimov, @asolino, I did investigate and indeed it was only a parsing bug.
The code recently changed for GetUserSPNs.py
but according the current stable 0.9.21 version
available on pypi
, you just need to change, in all example scripts
, address
by password
at this line
https://github.com/SecureAuthCorp/impacket/blob/8d4c91481b01dae9f62804893fcc74a40ffc7c45/examples/GetUserSPNs.py#L441
Yes. really. that tiny stuff that led this 2-year old bug, where we thought it was related to the LDAP communication, TLS and so !
After doing this tiny modification, I really ran the same 2 commands I tried in the original post, and it just worked flawlessly.
For the record, the really complex modifications I did to debug this:
225 targetParam = options.target+'@' 226 print('targetParam "%s"' % targetParam) 227 domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(targetParam).groups('') 228 229 print("parsing before stuff ; username: %s | password: %s | domain: %s" % (username,password,domain)) 230 #In case the password contains '@' 231 if '@' in password: 232 password = password + '@' + address.rpartition('@')[0] 233 address = address.rpartition('@')[2] 234 235 if domain == '': 236 logging.critical('Domain should be specified!') 237 sys.exit(1) 238 239 if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: 240 from getpass import getpass 241 password = getpass("Password:") 242 243 if options.aesKey is not None: 244 options.k = True 245 246 try: 247 print("parsing after ; username: %s | password: %s | domain: %s" % (username,password,domain)) 248 executer = GetADUsers(username, password, domain, options)
That gave me this at execution showing that the password field is altered, hence leading the original error:
targetParam "adyolo.swag/<user>:<pass>@192.168.200.130@"
parsing before stuff ; username: <user> | password: <pass> | domain: adyolo.swag
parsing after ; username: <user> | password: <pass>@192.168.200.130 | domain: adyolo.swag
Nice finding @maaaaz!
We will test it locally and update accordingly. Thanks!
Hey guys!
The proper use to run these scripts (GetADUsers, GetUserSPNs, GetNPUsers...) is by specifying the target as follows: domain/username[:password]
. The IP address must not be specified in the target. In case you need to define the IP address of the domain controller, you must use the parameter -dc-ip
.
In a recent commit, the regex that processes the target (domain/username[:password]
) was improved and the variable address
was removed.
@maaaaz,
The following is not an option
you just need to change, in all example scripts, address by password at this line
I worked on this problem some time ago, but this is not an easy task with the current process of passing/parsing user input in those scripts where an address can be provided, but is not required. Also it is due to the fact that the symbols used in an address are a subset of password alphabet symbols. So, there is no that symbol that allow to separate a password value from an address value as it could be done with the values of domain (before the first "/") and username (between the first "/" and the first ":")
For example, with the following string "domain/username:pass@1.1.1.1" specified by a user you will never know whether it is the password, "pass@1.1.1.1", or the password, "pass", and the address, "1.1.1.1". In the case where it is just a password, user must to specify the trailing @ sign by himself. It's not cool and the syntax will also look ugly ("domain/username:pass@1.1.1.1@")
This is probably a rare case, but it could happen, so it should be considered to avoid such problems in the future examples
There seems to be a misunderstanding. I mentioned that it was a bug, but now everything works fine. I should have noted that this problem is no longer relevant and can be closed Details are in @0xdeaddood's post https://github.com/SecureAuthCorp/impacket/issues/474#issuecomment-625949398
It seems the problem is still present in Impacket v.0.9.22
kali@kali:~/Downloads$ python3 GetUserSPNs.py spookysec.local/svc-admin -no-pass -debug
Impacket v0.9.22.dev1+20200921.175010.84c8d6a7 - Copyright 2020 SecureAuth Corporation
[+] Impacket Library Installation Path: /usr/local/lib/python3.8/dist-packages/impacket-0.9.22.dev1+20200921.175010.84c8d6a7-py3.8.egg/impacket
[+] Connecting to spookysec.local, port 389, SSL False
Traceback (most recent call last):
File "GetUserSPNs.py", line 506, in <module>
executer.run()
File "GetUserSPNs.py", line 266, in run
ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
File "/usr/local/lib/python3.8/dist-packages/impacket-0.9.22.dev1+20200921.175010.84c8d6a7-py3.8.egg/impacket/ldap/ldap.py", line 341, in login
raise LDAPSessionError(
impacket.ldap.ldap.LDAPSessionError: Error in bindRequest -> invalidCredentials: 8009030C: LdapErr: DSID-0C090690, comment: AcceptSecurityContext error, data 52e, v4563
[-] Error in bindRequest -> invalidCredentials: 8009030C: LdapErr: DSID-0C090690, comment: AcceptSecurityContext error, data 52e, v4563
Or am I missing something ?
This is not related to the original problem @sebastienPoussard .. You're not specifying target IP. Looks like you haven't specified the svc-admin
credentials.
Closing this issue since the original problem got clarified by @0xdeaddood.
Hello there,
I'm facing an issue while using
GetADUsers.py
andGetUserSPNs.py
, the LDAP bind fails and I don't know why. Entered credentials are good.Client config
Server config