impacket icon indicating copy to clipboard operation
impacket copied to clipboard

Implement kpasswd

Open Alef-Burzmali opened this issue 4 years ago • 3 comments

Implement the Kerberos Change Password and Set Password protocols. It fixes the second request of #1156.

As it is a completely different protocol than what smbpasswd.py is using, with different properties and constraints, I have created a new example script. It may be possible to merge the two, let me know if you would prefer it that way.

It differs from #1177 because it is not using SamrUnicodeChangePasswordUser2 to change the password, but the Kerberos Change Password protocol.

Alef-Burzmali avatar Oct 16 '21 22:10 Alef-Burzmali

Seems to be not working correctly when using the KRB5CCNAME

root@ubuntu:~/impacket/examples# python3 kpasswd.py -ts -newpass 'ASDqwe123' SITTINGDUCK.INFO/uberuser
Impacket v0.9.25.dev1+20211027.123255.1dad8f7f - Copyright 2021 SecureAuth Corporation

[2021-11-03 02:57:56] [*] Current password not given: will use KRB5CCNAME
[2021-11-03 02:57:56] [*] Changing the password of \
Traceback (most recent call last):
  File "kpasswd.py", line 141, in <module>
    kpasswd.changePassword(newPassword)
  File "kpasswd.py", line 59, in changePassword
    changePassword(self.username, self.domain, newPassword, self.oldPassword, self.oldPwdHashLM, self.oldPwdHashNT, self.aesKey, kdcHost=self.kdcHost)
  File "/usr/local/lib/python3.8/dist-packages/impacket-0.9.25.dev1+20211027.123255.1dad8f7f-py3.8.egg/impacket/krb5/kpasswd.py", line 278, in changePassword
    setPassword(clientName, domain, None, None, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/impacket-0.9.25.dev1+20211027.123255.1dad8f7f-py3.8.egg/impacket/krb5/kpasswd.py", line 289, in setPassword
    userName = Principal(clientName, type=PrincipalNameType.NT_PRINCIPAL.value)
  File "/usr/local/lib/python3.8/dist-packages/impacket-0.9.25.dev1+20211027.123255.1dad8f7f-py3.8.egg/impacket/krb5/types.py", line 90, in __init__
    raise KerberosException("invalid principal syntax")
impacket.krb5.types.KerberosException: invalid principal syntax

Klist:

root@ubuntu:~/impacket/examples# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: [email protected]

Valid starting     Expires            Service principal
11/03/21 02:24:45  11/03/21 12:24:45  krbtgt/[email protected]
        renew until 11/04/21 02:24:43

mubix avatar Nov 03 '21 03:11 mubix

Figured out the issue, target in the help needs to be updated:

positional arguments:
  target                [[domain/]username[:password]]

Where as the examples give an actual host for a target:

#       kpasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!'

mubix avatar Nov 03 '21 03:11 mubix

Thanks for noticing that. The DC could be an optional parameter (it was originally but I changed to parse_target instead of parse_credentials, causing the bug). However, I think it is better to be coherent with smbpasswd parameters.

Alef-Burzmali avatar Mar 03 '22 21:03 Alef-Burzmali

Rebasing to latest master as this PR received some attention for CVE-2022-32744

Alef-Burzmali avatar Nov 07 '22 18:11 Alef-Burzmali

We should wait for https://github.com/fortra/impacket/pull/1177 to be merged before reviewing this pull request.

alexisbalbachan avatar Feb 02 '23 15:02 alexisbalbachan

#1177 does not implement the same protocol. It uses SamrChangePasswordUser, with Kerberos autentication, whereas my PR implements the kpasswd protocol.

Some additional info here on the different protocols. Mine is 3. and 4., #1177 is 1.

Alef-Burzmali avatar Feb 12 '23 15:02 Alef-Burzmali

fingers crossed to see this one added

darkoperator avatar Apr 18 '23 20:04 darkoperator

Is there anything more I can do to help with the review of this PR, since it has been assigned?

Alef-Burzmali avatar May 10 '23 19:05 Alef-Burzmali

Hello, sorry for the delayed response. Despite https://github.com/fortra/impacket/pull/1177 (which has to be merged), we are thinking to integrate all the PRs related to password change/reset (https://github.com/fortra/impacket/pull/1304, https://github.com/fortra/impacket/pull/1207, and this one) into one example like changepaswd.py or similar. Let us know your opinions on that. thanks!

anadrianmanrique avatar May 12 '23 19:05 anadrianmanrique

Hello, Thanks for the answer!

If I understand correctly all these PR, we have:

  • current smbpasswd.py functionality of using SAMR over SMB transport, using NTLM authentication
  • #1177: adding Kerberos authentication, before continuing with SAMR over SMB transport
  • #1304: using SAMR over MS-RPC transport, with NTLM authentication. I guess it could be compatible with Kerberos auth too.
  • #1207: Adding "reset password" capability via SAMR over SMB transport. I think this one is a duplicate of what was implemented in #1171
  • #1189 (this one): implementing a different password change protocol, kpassword. This one does not use SAMR at all and requires Kerberos authentication.

It would make sense from an exploitation perspective to regroup all of these similar features in the same script. However, from an example code perspective, the script would be harder to understand if not planned correctly, especially because we would mix 3 different transport protocols. Up to you to decide if you prefer focusing on "ease of use for attackers" or "clarity of example scripts for developers".

If you want to go ahead on a single "changepasswd.py" script that merge all these PR, I'd be happy to give it a try in a new PR if no one is already working on it. I'd suggest an interface like this one:

usage: changepasswd.py [-h] [-ts] [-debug] (-newpass NEWPASS | -newhashes LMHASH:NTHASH) [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-altuser ALTUSER] [-altpass ALTPASS] [-althash ALTHASH]
                       [-protocol {smb-samr,rpc-samr,kpasswd}] [-reset] [-dc-ip ip address]
                       target

Change or reset password over different protocols.

positional arguments:
  target                [[domain/]username[:password]@]<targetName or address>

options:
  -h, --help            show this help message and exit
  -ts                   adds timestamp to every logging output
  -debug                turn DEBUG output ON
  -newpass NEWPASS      new password
  -newhashes LMHASH:NTHASH
                        new NTLM hashes, format is LMHASH:NTHASH

Authentication (target user changing their password):
  -hashes LMHASH:NTHASH
                        NTLM hashes, format is LMHASH:NTHASH
  -no-pass              Don't ask for password (useful for -k)
  -k                    Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command line
  -aesKey hex key       AES key to use for Kerberos Authentication (128 or 256 bits)

Authentication (optional, privileged user performing the change):
  -altuser ALTUSER      Alternative username
  -altpass ALTPASS      Alternative password
  -althash ALTHASH      Alternative NT hash

Method of operations:
  -protocol {smb-samr,rpc-samr,kpasswd}
                        Protocol to use for password change/reset
  -reset, -admin        Try to reset the password with privileges (may bypass some password policies)

Connection:
  -dc-ip ip address     IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter

Examples:
  SAMR protocol over SMB transport to change passwords (like smbpasswd.py, -protocol smb-samr is implied)
    changepasswd.py [email protected]
    changepasswd.py contoso.local/j.doe@DC1 -hashes :fc525c9683e8fe067095ba2ddc971889
    changepasswd.py -protocol smb-samr contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!'
    changepasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb
    changepasswd.py contoso.local/j.doe@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -k -no-pass

  SAMR protocol over SMB transport to reset passwords (like smbpasswd.py, -protocol smb-samr is implied)
    changepasswd.py contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!' -altuser administrator -altpass 'Adm1nPassw0rd!'
    changepasswd.py -protocol smb-samr contoso.local/j.doe:'Passw0rd!'@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/administrator -altpass 'Adm1nPassw0rd!' -reset
    changepasswd.py SRV01/administrator:'Passw0rd!'@10.10.13.37 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/SrvAdm -althash 6fe945ead39a7a6a2091001d98a913ab -reset
    changepasswd.py SRV01/administrator:'Passw0rd!'@10.10.13.37 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/DomAdm -k -no-pass -reset

  SAMR protocol over MS-RPC transport to change passwords
    changepasswd.py -protocol rpc-samr contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!'
    changepasswd.py -protocol rpc-samr contoso.local/j.doe@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -k

  SAMR protocol over MS-RPC transport to reset passwords
    changepasswd.py -protocol rpc-samr contoso.local/j.doe@DC1 -newpass 'N3wPassw0rd!' -altuser CONTOSO/SrvAdm -althash 6fe945ead39a7a6a2091001d98a913ab -reset
    changepasswd.py -protocol rpc-samr contoso.local/j.doe@DC1 -newhashes :126502da14a98b58f2c319b81b3a49cb -altuser CONTOSO/SrvAdm -k -reset

  Kerberos Change Password protocol (like kpasswd) (-newhashes is not supported)
    changepasswd.py -protocol kpasswd contoso.local/j.doe:'Passw0rd!'@DC1 -newpass 'N3wPassw0rd!' -k

  Kerberos Reset Password protocol (like kpasswd) (-newhashes is not supported)
    changepasswd.py -protocol kpasswd contoso.local/j.doe@DC1 -newpass 'N3wPassw0rd!' -altuser CONTOSO/SrvAdm -k -reset

Alef-Burzmali avatar May 14 '23 16:05 Alef-Burzmali

Wow that's really great and helpful feedback! We haven't started merging those PRs yet Thank you!

anadrianmanrique avatar May 17 '23 15:05 anadrianmanrique

As #1559 was merged and is a superset of this PR, I am closing this one.

Alef-Burzmali avatar Jul 17 '23 19:07 Alef-Burzmali