Huli Security Group

Huli Security Group

Your Friendly Neighbourhood Auditors

01 Sep 2021

Reasonably Secure Terminal

In this post we’ll go over how to configure a basic secure terminal, i.e. a client device which is used to connect to remote services with no important data stored on its local disk.

A typical use-case would be your trading laptop accessing your exchange accounts.

Recommendations

We’ll use two devices: a secure Linux laptop, which will run the client software (usually a web browser) and a hardened Android phone, which we will use for two-factor authentication.

Our current preferred Linux laptop is a NitroPad running QubesOS. Everything basically works out of the box, documentation is available for when it doesn’t 12, the hardware runs Coreboot, and the OS has been designed with security in mind and has a good track record.

Make sure to use different Qubes for trading, research (random web browsing), etc.

For our 2FA device, we’ll use a Google Pixel running GrapheneOS (formerly CopperheadOS). Since we’ll basically be using this as a dumb authentication device, software compatibility is mostly not an issue (but hi, Interactive Brokers 😭).

We’d prefer to use a SoloKey or NitroKey, but since you’ll almost certainly run into sites that don’t support U2F or even require you to use their own apps, we would need a phone anyway, so it’s easiest to just use an authenticator running on the phone for everything.

Additionaly, we might need a phone number to sign up for certain services, in which case we can just get a virtual SIM from e.g. Silent Link and plug that into our 2FA device (do not ever use this number for anything else)!

Finally, it’s nice to have the option to run things like Ledger Live, which may not work on Qubes, on the phone.

The overall setup is as follows:

  • the phone has an authenticator app (Duo or Aegis), which generates TOTPs
  • the laptop has a password manager (KeePassXC), which stores all of your logins
  • the only data that must be backed up is the password manager’s vault and the 2FA backup codes, both as symmetrically encrypted tarballs
  • you’ll have to remember three passphrases:
    1. the phone PIN,
    2. the laptop login (which we re-use to unlock the password manager: since the passwords are the only thing protected by the login, we might as well), and
    3. the backup key

Software

We’ll mostly be using Firefox with settings and addons recommended by PrivacyTools (you’ll have to turn them on one-by-one and check that they don’t break your favorite exchange’s web app).

If you are going to be using your terminal to talk to your hardware wallets, you’ll also want Electrum, MetaMask, the BitBox app, etc.

Security Analysis

Assuming that sites require 2FA for each operation, i.e. cached logins are not an issue, only full compromise (both devices and both passphrases) results in access.

Getting into your accounts by compromising your backups is easier:

  • adversary needs get into your storage location (e.g. a private GitLab repo or ProtonMail), and
  • adversary needs to steal your passphrase

Obviously we can’t trust the storage provider, so the security of your backups hinges entirely on the strength and confidentiality of your passphrase.

If you generate fresh passwords and OTPs when setting up your terminal initially, and then rotate those once per year, you’ll only need to generate new backups (type your encryption key) once per year, which you’ll hopefully manage to do in a safe environment.

If you choose a strong passphrase for your backups (e.g. 8 words chosen at random from a large dictionary), we feel that this is an acceptable usability trade-off.

Conclusion

We presented a straight-forward, reasonably secure terminal design which requires you to remember only three distinc passphrases. We strongly suggest setting a daily reminder and taking a few minutes every morning to ensure recall of your backup passphrase. You’ll be typing the phone PIN and laptop login frequently, so recall shouldn’t be an issue.


  1. NitroPad docs ↩︎

  2. QubesOS docs ↩︎