n0fate / chainbreaker

Mac OS X Keychain Forensic Tool
GNU General Public License v2.0
816 stars 157 forks source link

macOS 11 Big Sur Private Key Table is not available #19

Closed aritgithub closed 1 year ago

aritgithub commented 3 years ago

python2.7 chainbreaker.py -p --dump-private-keys "/Users/xxx/Library/Keychains/login.keychain-db"

...
WARING - [!] Private Key Table is not available
INFO - 0 Private Keys
...

Is this a Big Sur issue?

Ret2lib commented 3 years ago

Same issue on OSX catalina 10.15.7

pencarsa commented 3 years ago

Will this be ever addressed?

vetsin commented 3 years ago

I'm not sure what the actual issue is, but this super hack here makes it work:

https://github.com/vetsin/chainbreaker

The author will want to review why the table_list or table_enum isn't as expected (not sure which is wrong)

jhonMalcom79 commented 3 years ago

what version did you tried it on? I tried on Catalina and couldn't make it work

vetsin commented 3 years ago

Made it work for my system - mojave 10.14.6 - can't tell you how to fix it right but you may need to do some debugging and change if table_name == 23972: to whatever value it is for you

jhonMalcom79 commented 3 years ago

I can get the value that is for me but should I set table_name to 16 or to something else? How did you get to the 16?

Thanks @vetsin

jhonMalcom79 commented 3 years ago

What I did is the following: 1) Got rid of the try catch to force chainbraker.py to crash:

def dump_private_keys(self):
        entries = []
        #try:
        table_meta, private_key_list = self._get_table_from_type(CSSM_DL_DB_RECORD_PRIVATE_KEY)
        for i, private_key_offset in enumerate(private_key_list, 1):
            entries.append(
                self._get_private_key_record(private_key_offset))

        #except KeyError:
        #    self.logger.warning('[!] Private Key Table is not available')
        return entries

2) Printing table_name:

def _get_base_address(self, table_name, offset=None):
        print("Table_name: "+ str(table_name))
        if table_name == 23972:
            table_name = 16

I get:

2021-05-11 17:57:23,181 - INFO - Dump Start: 2021-05-11 17:57:23.179151
Table_name: 20360
Traceback (most recent call last):
  File "chainbreaker.py", line 1336, in <module>
    'records': keychain.dump_private_keys(),
  File "chainbreaker.py", line 153, in dump_private_keys
    self._get_private_key_record(private_key_offset))
  File "chainbreaker.py", line 405, in _get_private_key_record
    record = self._get_key_record(self._get_table_offset(CSSM_DL_DB_RECORD_PRIVATE_KEY), record_offset)
  File "chainbreaker.py", line 444, in _get_key_record
    base_addr = self._get_base_address(table_name, record_offset)
  File "chainbreaker.py", line 556, in _get_base_address
    base_address = _APPL_DB_HEADER.STRUCT.size + self._get_table_offset(table_name)
  File "chainbreaker.py", line 215, in _get_table_offset
    return self.table_list[self.table_enum[table_name]]
KeyError: 20360

I tried to change your 23972 for the 20360 that I get but I get:

2021-05-11 18:05:48,743 - INFO - Dump Start: 2021-05-11 18:05:48.739173
Table_name: 20360
2021-05-11 18:05:48,786 - INFO - 1 Private Keys
2021-05-11 18:05:48,787 - INFO -        [+] Private Key
2021-05-11 18:05:48,788 - INFO -         [-] Print Name: Imported Private Key
2021-05-11 18:05:48,788 - INFO -         [-] Key Class: CSSM_KEYCLASS_PRIVATE_KEY
2021-05-11 18:05:48,789 - INFO -         [-] Key Type: CSSM_ALGID_RSA
2021-05-11 18:05:48,790 - INFO -         [-] Key Size: 2048
2021-05-11 18:05:48,790 - INFO -         [-] Effective Key Size: 2048
2021-05-11 18:05:48,791 - INFO -         [-] CSSM Type: Core CSP (local space)
2021-05-11 18:05:48,791 - INFO -         [-] Base64 Encoded PrivateKey: [Invalid Password / Keychain Locked]
2021-05-11 18:05:48,792 - INFO -
2021-05-11 18:05:48,793 - INFO -
2021-05-11 18:05:48,794 - INFO -

I use this command python2 chainbreaker.py --dump-private-keys --password-prompt my.keychain-db

and I'm positive that the password I'm using is the one I have on my OSX.

Is there anything that you see that I'm doing wrong?

NOTE: I scp the keychain from my OSX to a Debian where I'm running all this. Should this be a problem? NOTE2: As password I'm using the same one that my OSX user but it seems to be invalid to decrypt the keychain. What password should be using then? I've verified that the password I'm using is not the one expected by trying to crack the $keychain$... with my password in a dictionary with unsuccessful results.

vetsin commented 3 years ago

You got past the bug most of us are having, you aren't unlocking it and I don't know why. I only did it on the System keychain and used the key file.

Ret2lib commented 3 years ago

This worked for what I wanted.

https://github.com/gremwell/chainbreaker

hypnoticpattern commented 3 years ago

Hi @vetsin, I am using BigSur 11.5.2 (20G95) and implemented your fix hardcoding the table_name ID I get when the exception raises. The private keys are exported and the name of the files created by chainbreaker is correct but the content seems to be corrupted. Tried both openssl and KeyChain app to reimport the key.

$ openssl rsa -noout -text -check -in keys/private/key.key
unable to load Private Key

did you have the same issue?

bobsoppe commented 3 years ago

To get a private key from the system keychain you need to disable SIP (https://apple.stackexchange.com/a/208481), so that you can access the SystemKey stored at /var/db/SystemKey

sudo python ./chainbreaker.py --export-all --unlock-file /var/db/SystemKey --output out /Library/Keychains/System.keychain would be able to export everything from the system keychain.

You still need to hardcode the correct table with the steps written in https://github.com/n0fate/chainbreaker/issues/19#issuecomment-839357165

hypnoticpattern commented 2 years ago

The private keys I am trying to get are in the user folder like the ones @aritgithub was trying to retrieve.

dKtKRVn commented 2 years ago

22 done

NgoKimPhu commented 2 years ago

@hypnoticpattern The fix works on my BigSur 11.6.2 too. The keys were correctly exported, your command only failed because you were missing -inform DER.

Edit: yes my private keys are marked as non-exportable (unable to export from Keychain Access app). I only run with --export-private-keys btw, and the output log during the export shows the base64 of the private keys.

hypnoticpattern commented 2 years ago

@NgoKimPhu thanks for the fix. The certificates that were exported were malformed in my case. I tried to import them in other tools before trying openssl (e.g. Web proxies for MTLS) but got errors saying that they were malformed and then I used openssl to check the format (with the wrong command). I run the tool again last week on Monterey 12.2.1 and I am getting 0 Private Keys, 0 Public Keys and 10 x509 Certificates so there is something that it's not working for me since other items such as normal passwords are exported correctly. Out of curiosity. Are your private keys marked as non-exportable in key chain?

hypnoticpattern commented 2 years ago

Can't reproduce the test I did in August but I just tried again and figured out why chainbreaker did not work on Monterey last week. Monterey uses a different table name for private keys and I completely missed the BIG WARNING message in the tool output informing me of that. After adding a new if condition here with table name 24328 (maybe specific to Monterey 12.2.1?) I was able to export the private keys. @NgoKimPhu thanks for making me look at it again!

davidchoo12 commented 2 years ago

Here is how I managed to export private keys for Big Sur 11.6.5:

  1. Disable System Integrity Protection
  2. Apply this change
  3. sudo python2 chainbreaker.py /Library/Keychains/System.keychain --unlock-file /var/db/SystemKey --dump-private-keys
pencarsa commented 2 years ago

I get private keys from System.keychain in the format name.key, 1KB each file, however, each is not readable. What am I missing ?

hypnoticpattern commented 2 years ago

@pencarsa what OS version do you have? did you patch the code here based on the table number? Can you post the tool output?

pencarsa commented 2 years ago

@pencarsa what OS version do you have? did you patch the code here based on the table number? Can you post the tool output?

@hypnoticpattern Thanks! Here are some details: OS: Monterey 12.3.1 Code: 556 def _get_base_address(self, table_name, offset=None): 557 if table_name >= 0x4000 and table_name < 0x5000: 558 table_name = 15 559 if table_name >= 0x5000 and table_name < 0x6000: 560 table_name = 16 561 base_address = _APPL_DB_HEADER.STRUCT.size + self._get_table_offset(table_name) 562 if offset: 563 base_address += offset

Tool output: ChainBreaker 2 - https://github.com/gaddie-3/chainbreaker 2022-05-09 21:22:03,434 - INFO - Runtime Command: chainbreaker.py -d /Library/Keychains/System.keychain --unlock-file /var/db/SystemKey --export-all --output out 2022-05-09 21:22:03,434 - INFO - Keychain: /Library/Keychains/System.keychain 2022-05-09 21:22:03,434 - INFO - Keychain MD5: dcbe47b235cf7fbe6d478b908f2db39e 2022-05-09 21:22:03,434 - INFO - Keychain 256: fb2b63894837680590f21b8ade98340b2a2f283e20324d963fcab49c794bf16d 2022-05-09 21:22:03,434 - INFO - Dump Start: 2022-05-09 21:22:00.508443 2022-05-09 21:22:03,434 - INFO - Dump Summary: 2022-05-09 21:22:03,434 - INFO - 1 Keychain Password Hash 2022-05-09 21:22:03,435 - INFO - 73 Generic Passwords 2022-05-09 21:22:03,435 - INFO - 0 Internet Passwords 2022-05-09 21:22:03,435 - INFO - 0 Appleshare Passwords 2022-05-09 21:22:03,435 - INFO - 3 Private Keys 2022-05-09 21:22:03,435 - INFO - 2 Public Keys 2022-05-09 21:22:03,435 - INFO - 20 x509 Certificates 2022-05-09 21:22:03,435 - INFO - Dump End: 2022-05-09 21:22:03.434783

Private Keys have a format: somename.key

pencarsa commented 2 years ago

@hypnoticpattern forget about it, all works fine on Monterey. It was a matter of keys and crts conversion. For people who want to move these keys+crts as p12 files to another Mac's Keychain there are few steps to follow:

  1. convert DER keys to PEM keys openssl rsa -inform DER -in name.key -out pem.key
  2. convert crt files to PEM certs openssl x509 -inform DER -in name.crt -out pem.cert -outform PEM
  3. create pkcs12 file openssl pkcs12 -export -clcerts -inkey pem.key -in pem.cert -out name.p12 -name "yourname"
  4. import name.p12 file on your other device to a login or system keychains
n0fate commented 1 year ago

Sorry for being late. I fix some code for this issues. checkout #21