--default-cache-ttl set the time a cache entry is valid.
This time is checked inside housekeeping() function.
This function is executed only when agent_put_cache() or agent_get_cache() functions are called.
In normal GPG usage like:
- User sign file using command line
- User back to normal work
no more commands are send to gpg-agent so housekeeping() function is not executed.
Basically this means that in most cases passphrase is stored in gpg-agent memory longer than default 600 seconds until new command is send to gpg-agent.
This can be used in specific situations by attacker, who has access to current user session, for stealing private key without knowing passphrase.
Working POC for this attack under Windows is available here:
https://github.com/kacperszurek/gpg_reaper
Steps to reproduce:
- Start new gpg-agent instance with small cache time:
cd c:\Program Files (x86)\GnuPG\bin taskkill /im gpg-agent.exe /F gpg-agent.exe --daemon --default-cache-ttl 2
- Sign some test file
gpg --sign test.txt
- You will be asked for passphrase
- Repeat step 2. Each time pinentry will ask you for passphrase because our 2 seconds cache expired
- Run GPG Reaper
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile out.txt
As you can see we dumped private key.
Conclusions
housekeeping() function should be called every few seconds so passphrase will be removed from memory as soon as it expired.
Probably handle_tick() function might be good for this.