
Analisi di una vulnerabilità logica nel client SSH di macOS che porta all'esposizione della passphrase del client a un attaccante locale.
Questo documento presenta sia un'analisi di una vulnerabilità logica identificata nel binario ssh su macOS (la mia prima vulnerabilità software!) sia un'analisi della patch che mostra come Apple ha risolto la vulnerabilità. Ho segnalato il problema ad Apple tramite il programma Apple Security Bounty alla fine del 2022, che è stato successivamente risolto in macOS Ventura 13.5 e ha generato CVE-2023-42829 (🎉). Il problema porta alla divulgazione in chiaro delle passphrase SSH salvate nel portachiavi 'Login' locale dell'utente macOS (nel gruppo di accesso com.apple.ssh.passphrases) a un utente malintenzionato locale.
Disclaimer:
Questo rapporto è fornito solo a scopo educativo, dopo aver seguito corretti processi di divulgazione responsabile. L'analisi è fornita così com'è, e qualsiasi ulteriore pubblicazione o utilizzo di queste informazioni dovrebbe attenersi alle linee guida per la divulgazione responsabile.
Flusso di alto livello dopo la patch
Flusso di alto livello prima della patch
com.apple.private.security.clear-library-validation| Hardware | Software del sistema operativo |
|---|---|
| MacBook Pro M1 2021 | /usr/bin/ssh @ macOS Ventura build 13.0.1 (22A400) |
Il seguente proof-of-concept illustra la semplicità dello sfruttamento della vulnerabilità, passando una libreria dinamica al flag -I del binario ssh:
jamesd@local build % ssh -I /Users/jamesd/rome.dylib [email protected]
SSH Private Key Passphrase -> 'SuperSecret!!@@$'
Parliamo di come è stata scoperta e perché è successo!
Una volta stavo usando il binario ssh per qualcosa di innocuo e ho digitato erroneamente il flag -i (usato per passare un file di identità SSH) con il flag -I e ho ricevuto il seguente stdout:
jamesd@local build % ssh -I /Users/jamesd/.ssh/id_rsa something@somewhere
dlopen /Users/jamesd/.ssh/id_rsa failed: dlopen(/Users/jamesd/.ssh/id_rsa, 0x0002): tried: '/Users/jamesd/.ssh/id_rsa' (not a mach-o file), ...
...
Dopo aver controllato gli entitlement del binario ssh...
jamesd@local build % ldid -e /usr/bin/ssh # dump the entitlements of the /usr/bin/ssh binary
<key>com.apple.private.security.clear-library-validation</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>com.apple.ssh.passphrases</string>
</array>
...la mia curiosità è stata stuzzicata - il binario ha entitlement per leggere da un gruppo di accesso protetto del portachiavi (com.apple.ssh.passphrases), possiede l'entitlement com.apple.private.security.clear-library-validation, e ssh sta tentando di eseguire dlopen() sulla mia chiave privata?
A quanto pare, ssh supporta l'autenticazione a un sistema remoto tramite qualcosa chiamato pkcs11, uno standard per operazioni crittografiche su moduli di sicurezza hardware (HSM) (https://docs.aws.amazon.com/cloudhsm/latest/userguide/pkcs11-library.html).
Non dobbiamo preoccuparci dei dettagli specifici di pkcs11 ai fini di questo documento, a parte il fatto che il client fornisce una libreria pkcs11 (dinamica) a ssh -I.
com.apple.private.security.clear-library-validationSebbene concettualmente equivalente, com.apple.private.security.clear-library-validation differisce dal precedente entitlement equivalente (com.apple.security.cs.disable-library-validation) in quanto com.apple.private.security.clear-library-validation richiede di effettuare la syscall csops() passando CS_OPS_CLEAR_LV per controllare l'abilitazione/disabilitazione della convalida delle librerie al fine di mantenere un maggiore controllo sull'integrità del processo in fase di esecuzione (rispetto a com.apple.private.security.clear-library-validation che presumibilmente consentirebbe di caricare qualsiasi libreria senza controllo in fase di esecuzione). (https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/kern_proc.c) (https://theevilbit.github.io/posts/com.apple.private.security.clear-library-validation/)
Poiché csops(CS_OPS_CLEAR_LV) viene chiamato prima di dlopen() della nostra libreria, quest'ultima viene semplicemente caricata e il costruttore viene eseguito, consentendoci di fornire una libreria dinamica dannosa mascherata da libreria pkcs11 e di eseguire codice dal contesto di /usr/bin/ssh e utilizzare l'entitlement keychain-access-groups.
Forse la patch prevedeva controlli eseguiti sul binario prima di chiamare csops() per verificare specifiche identità di firma attendibili?
No!
Dopo il rilascio della patch (22G74) ho confrontato l'implementazione non sicura di pkcs11_add_provider() (il metodo in cui viene effettuata la chiamata a dlopen()) e sembrava identica alla versione con patch - ma manca un entitlement in /usr/bin/ssh?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>keychain-access-groups</key>
<array>
<string>com.apple.ssh.passphrases</string>
</array>
</dict>
</plist>
Ma sicuramente Apple non avrà rimosso il supporto pkcs11 da SSH? Ho provato a riesplorare la vulnerabilità usando il mio PoC e ho scoperto che, sebbene la mia libreria fosse caricata, non poteva più leggere dal gruppo di accesso del portachiavi e sembrava essere eseguita nel contesto di /usr/libexec/ssh-apple-pkcs11 (un binario che non avevo mai visto prima) che possiede i seguenti entitlement:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.private.security.clear-library-validation</key>
<true/>
</dict>
</plist>
Un commento nella syscall csops() per CS_OPS_CLEAR_LV (https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/kern_proc.c) menziona la possibilità di rieseguire un binario senza convalida della libreria come alternativa a CS_OPS_CLEAR_LV, piuttosto che essere utilizzata in combinazione. Quindi perché la routine logicamente difettosa è ancora presente in pkcs11_add_provider() in /usr/bin/ssh se ora esiste un binario helper aggiuntivo? e perché l'implementazione appare invariata nella patch?
Bene, a quanto pare, la patch non consisteva nell'aggiungere un binario helper, ma prevedeva la distribuzione di due binari ssh in macOS: /usr/bin/ssh e /usr/libexec/ssh-apple-pkcs11 - entrambi identici tranne che per i loro entitlement (ho usato Diaphora per verificarlo):
Dopo aver condotto un'analisi dinamica sul binario ssh con patch, è stato aggiunto un controllo aggiuntivo nella routine (piuttosto grande) start() di ssh che viene utilizzata, all'uso delle funzionalità pkcs11, per determinare se il binario è in esecuzione nel contesto di /usr/bin/ssh o /usr/libexec/ssh-apple-pkcs11:
Nel blocco verde, possiamo osservare una chiamata a SecTaskCopyValueForEntitlement() (il valore passato è "com.apple.private.security.clear-library-validation") che viene poi (nel blocco arancione) valutata e causa una chiamata condizionale alla routine di riesecuzione se l'entitlement "com.apple.private.security.clear-library-validation" non è presente per l'attività/processo corrente (blocco rosso).
Ciò comporta l'utilizzo del binario ssh-apple-pkcs11 con meno entitlement quando si carica la libreria pkcs11 fornita dall'utente (disabilitando di fatto le funzionalità relative al portachiavi di ssh), e l'utilizzo di ssh dove non devono essere caricate librerie non attendibili (abilitando le funzionalità relative al portachiavi di ssh).
Possiamo anche verificare che sia così tramite il debug del ssh con patch.
Se eseguiamo il debug del binario ssh con patch (distribuito in macOS 22G74) e impostiamo breakpoint su execv(), possiamo effettivamente notare una chiamata a execv() quando si fornisce il flag -I, che non si verifica quando si avvia ssh senza utilizzare le funzionalità pkcs11:
Ho segnalato il problema ad Apple tramite il programma Apple Security Bounty alla fine del 2022, che è stato successivamente risolto in macOS Ventura 13.5 e ha generato CVE-2023-42829 (🎉).
Questo documento è una pubblicazione indipendente e non è stata autorizzata, sponsorizzata o approvata in altro modo da Apple Inc. macOS, iOS e iWork sono marchi di Apple Inc.