Pretty Good Security

Seems like a lot of companies are getting hacked these days, even companies that put a lot of effort into security. There are a lot of reasons for this, but I believe there are three main causes.

First, much of the dialog around information security security is controlled by large companies that are financially incentivized to divert attention towards solutions that are easily productized.

A good example is Antivirus. Most AV hasn’t provided good information security value for a while. In many cases, it weakens overall security by increasing attack surface area, breaking TLS and weakening browser security. Justin Shuh, the lead security tech on the Chrome browser project once tweeted “AV is my single biggest impediment to shipping a secure browser”.

Unfortunately, these ideas tend to be codified in frameworks like ISO27001 and taught in certificating courses like the CISSP. Password rotation is another great example. We can empirically prove that it results in weaker passwords, but information security practitioners do it anyway, for compliance purposes. Even the FTC thinks forced password rotation is a bad idea.

Second, there is way too much focus on 0-day and APT.

No one is going to burn an expensive high-profile 0-day on your organization. Most adversaries don’t need or use exploits. Go ask any competent penetration testing professional how many exploits they used on their last engagement.

APT is not new–it’s basically just a new word for hacking. Hackers have been using phishing, client-side exploits, malware and lateral movement since at least the 1990s. The over-focus on APT leads people to buy next-gen security magic boxes, and basically ignore IT best-practices that address far riskier avenues of attack.

Third, there are a ton of resources on hacking and penetration testing, but far fewer quality resources on modern network defence. Go to any security conference to see this in action. The number of “hacker show and tell” talks about how to break stuff out numbers defensive talks 10 to 1. Most of the these talks don’t provide any suggestions on how to design controls for or mitigate the issues they describe.

It seems there is a lot of noise and very little signal. So what can we do that’s practical and risk focused?

A Case Study

It’s helpful to examine this from a macro scale to a micro scale to fully understand the issue. As it turns out, we have empirical data on security incidents, breaches and attacker TTPs (tools, techniques and procedures).

Reports like Mandiant M-Trends and the Verizon Data Breach Investigations Report are a gold mine of information. I think they’re great resources for deciding how to dedicate time and resources for your information security program.

We also have micro scale views on the mechanics of real breaches, such as this video of Phineas Phisher hacking a web site and his (or her) write up on how Hacking Team was hacked. These resources contain strong lessons on operating system hardening, network segmentation and rigorous adherence to IT best-practices.

There is also a wealth of information available on tools, tactics and procedures used by adversaries. A recent example I’d like to highlight is the Medium article by Chris McNab describing the TTPs used by Yahoo hacker Alexsey Belan.

I highly recommend reading that article before proceeding. There’s a strong trend across his techniques, the Phineas Phisher hacks and the breach data statistics. It’s an issue that penetration testers have been talking about for years: reuse of stolen trust material (passwords, private keys, tokens and cookies).

To mitigate this issue, we need our systems to make security decisions based on trust material that can’t be stolen or reused. But enough talk, let’s roll up our sleeves and get to work.

Two-Factor Authentication

Multi factor authentication typically has a few pain points when it comes to enterprise implementation. First, how do we integrate it into the myriad of technologies in a typical enterprise network? Second, how do we avoid just moving the problem around. In other words, how do we avoid using things like software certificates that can be stolen with malware?

To solve the first issue, I recommend using Duo Security. I know, I know… vendor pitches are not cool. But in this case I have a practical reason for recommending them: their documentation is awesome.

In the real world, you’re going to need some help with all the integration. Otherwise you’re going to get bogged down maintaining integration code with a constantly shifting landscape of enterprise software products. There are only so many hours in a day–make that someone else’s problem.

I also recommend that you don’t just roll out 2FA on the perimeter. Contrary to popular belief, 2FA isn’t something that just goes on the VPN. Your internal network is not that much more secure than the Internet. You need to integrate it everywhere you possibly can in order to provide the best security value. It doesn’t cost extra for more integrations.

To get started, just sign up. It’s free for up to 10 users and perfect for securing your home lab or personal cloud resources. If you want play with the advanced features, they have a 30-day demo available too.

If we just stopped there, that would actually be a big step up. However, I think we can do better.

Hardware Security

2FA in this form is probably going to be inconvenient. If you use the SMS or phone methods, it introduces a delay that inconveniences users (and it’s not very secure). The app push model is fairly secure, but still has a bit of latency plus the hassle of having to unlock your phone all the time (unless you happen to have an Apple Watch). I say fairly secure because it does rely on your users not rooting/jailbreaking their device or running old Android versions. Unless you have corporately issued phones with strong MDM policy this is definitely not going to be the case.

For these reasons, I recommend hardware-based security tokens. The token you want is the Yubikey 4. It has a killer feature that I’ll dig into later. The Yubikey 4 comes in three variants, the full size version, the mini, and the 4C for USB-C.

yubikey-4-nano-usb-c-trio-crop-1030x686

The Yubikey acts like a keyboard. You just plug it in (or in the case of the mini, just leave it plugged in) and tap the gold button to input your 2FA code. It even presses “enter” for you. Asking your users to tap a gold button when they login is not a very big ask.

To use the Yubikey with Duo, you can reprogram it with the Yubikey personalization tool as described here. However, for compatibility with some applications (like OpenVPN), you may have to reprogram it with 6-digit HOTP. This is fairly simple to do, just open the personalization tool, select OATH-HOTP then select 6-digit code and no token identifier.

yubikey_oath_hotp_configuration

You can import the seed value into the Duo admin panel using CSV import. I strongly recommend performing this process on a dedicated machine running up-to-date and validated software. Please don’t generate seeds on the same box you use to check your mail and surf the web or you’re going to have a bad time.

But wait, there’s more! They also support U2F. The Universal Second Factor standard is a relatively new technology that works with the Chrome browser. Essentially, a compatible web site can use a Javascript API to ask the key to generate a public and private key pair for the site’s origin. Later, the site can send a nonce and some other data to the same API and the key will return a signed version as proof of possession of the private key. The private key always lives on the token and cannot be extracted.

U2F is supported on Github, Google, Dropbox and many other sites. It’s totally painless to use. It can also be used with web-based integrations for Duo.

However, that’s not the killer feature of the Yubikey. There’s one feature that everyone should be using, but I don’t see a lot of people leveraging it today.

GPG and the Yubikey

GPG integrates with the Yubikey, allowing you to store your GPG keys securely in hardware. The Yubikey 4 also supports 4096-bit RSA, which provides very strong security.

GPG can do some pretty amazing things. GPG can act as an SSH agent. Not just for Linux and macOS machines–it can interface with PuTTY on Windows systems as well.

GPG also allows you to perform Git signing. You can integrate Git signing with your CI system as well. This means that you can prevent unsigned commits from running tests or being deployed. You only need to maintain a list of trusted public keys for this to work, and generally it’s not necessary to rotate them unless someone loses their key.

GPG can also be used to encrypt mail. Now I realize that using GPG for mail encryption isn’t perfect, but I guarantee you it’s better than using ZIP encryption and communicating the password via SMS (or whatever you’re doing today).

Warning: The setup for this is an ordeal. Sorry. It’s open source software. But if you’re willing to stick it out, I promise that it’s very convenient and wickedly secure to use day-to-day.

Step 1 – Setup Key Generation Environment

Note: This process is a variation of the guide found here.

Download Tails. Tails is designed for security, is regularly updated, and includes a compatible version of GPG preinstalled. Make sure you validate the image according to their instructions.

Burn the image to either a bootable USB disk or a CDROM, depending on the hardware you have kicking around. If you don’t know how to create a bootable USB disk, Google it.

Now boot into Tails. You will be greeted with a menu similar to the one below. Choose “Yes” for more options.

1_more-options

Now go ahead and disable networking and set a root password.

Once booted into Tails, start a Terminal and insert a fresh Yubikey 4. We’re now ready to start generating keys.

Step 2 – Master Key Generation

First, setup a baseline config:

$ cat << EOF > ~/.gnupg/gpg.conf
use-agent
personal-cipher-preferences AES256 AES192 AES CAST5
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
cert-digest-algo SHA512
s2k-digest-algo SHA512
s2k-cipher-algo AES256
charset utf-8
fixed-list-mode
no-comments
no-emit-version
keyid-format 0xlong
list-options show-uid-validity
verify-options show-uid-validity
with-fingerprint
EOF

Now create a master key pair. I don’t recommend using a strong password. We’re going to encrypt these files for offline storage anyway. The protection passphrase will get keyed in dozens of times for this process, so pick something easy to type.

$ gpg --gen-key

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: Phikshun
Email address: phikshun@example.com
Comment:
You selected this USER-ID:
    "Phikshun <phikshun@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.

gpg: key 0xFF3E7D88647EBCDB marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
pub   4096R/0xFF3E7D88647EBCDB 2016-05-24
      Key fingerprint = 011C E16B D45B 27A5 5BA8  776D FF3E 7D88 647E BCDB
uid                 [ultimate] Phikshun <phikshun@example.com>

Note that this key cannot be used for encryption.  You may want to use
the command "--edit-key" to generate a subkey for this purpose.

You’ll of course want to use your actual name and email address, especially if you’ll be publishing your keys to a key server. I strongly recommend using a 4096-bit key, and you’ll probably want to key to never expire.

Keep the passphrase you used handy. You’ll need it again shortly.

For convenience, save your key ID to a shell variable:

$ KEYID=0xFF3E7D88647EBCDB

Now create a revocation certificate. This is necessary so that you have a way to revoke the keys if they become lost of stolen.

$ gpg --gen-revoke $KEYID > ~/.gnupg/revoke.txt

sec  4096R/0xFF3E7D88647EBCDB 2016-05-24 Phikshun <phikshun@example.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
>
Reason for revocation: Key has been compromised
(No description given)
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0xFF3E7D88647EBCDB, created 2016-05-24

ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

Now backup your master key:

$ gpg --armor --export-secret-keys $KEYID > ~/.gnupg/master.key

Step 3 – Sub Key Generation

Now we’re going to create subkeys. We will use separate keys for signing, encryption and authentication. They’re all subkeys of the master key we just generated.

Edit the key to create subkeys:

$ gpg --expert --edit-key $KEYID

Secret key is available.

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: ultimate
[ultimate] (1). Phikshun <phikshun@example.com>

First we’ll create the signing key:

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0xFF3E7D88647EBCDB, created 2016-05-24

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

...................+++++
..+++++

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: ultimate
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
[ultimate] (1). Phikshun <phikshun@example.com>

Now we generate an encryption key:

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0xFF3E7D88647EBCDB, created 2016-05-24

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

.+++++
...........+++++

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: ultimate
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
[ultimate] (1). Phikshun <phikshun@example.com>

And finally we generate the authentication key:

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0xFF3E7D88647EBCDB, created 2016-05-24

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 8

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? e

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? a

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

+++++
.....+++++

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: ultimate
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
sub  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never       usage: A
[ultimate] (1). Phikshun <phikshun@example.com>

gpg> save

Step 4 – Check Your Work

Whew! Yeah, that’s a lot of work. We’re still not out of the woods yet though.

Let’s pause to check our work so far:

$ gpg --list-secret-keys
/home/user/.gnupg/secring.gpg
-------------------------------
sec   4096R/0xFF3E7D88647EBCDB 2016-05-24
      Key fingerprint = 011C E16B D45B 27A5 5BA8  776D FF3E 7D88 647E BCDB
uid                            Phikshun <phikshun@example.com>
ssb   4096R/0xBECFA3C1AE191D15 2016-05-24
ssb   4096R/0x5912A795E90DD2CF 2016-05-24
ssb   4096R/0x3F29127E79649A3D 2016-05-24

We can also verify our keys using the automated key best practice checker:

$ hkt export-pubkeys $KEYID | hokey lint

You should see green output. If you see red, it means your key has failed a check.

Now let’s save a copy of our keys so we can back everything up:

$ gpg --armor --export-secret-keys $KEYID > ~/.gnupg/mastersub.key
$ gpg --armor --export-secret-subkeys $KEYID > ~/.gnupg/sub.key

Step 5 – Backup Your Keys

We just generated keys in software. This doesn’t really solve our problem, because the keys can still be stolen with malware if placed on a general purpose computer with Internet access. We’re going to move them into the Yubikey 4 in a later step.

However, before we do that we need to back them up on an encrypted USB disk. Because our keys will be stored in hardware for daily use, they cannot be extracted. Keeping an encrypted backup ensures we can move them back to a new Yubikey if our existing key becomes damaged, or revoke the keys if it gets stolen.

To make an encrypted USB drive, you can follow the steps in the Tails documentation here. Randomly generate a long password and store it in a password manager. You probably won’t use it for a while, so don’t try and remember it.

Once you have an encrypted drive set up, go ahead and copy all the files in the ~/.gnupg folder into the encrypted volume. Unmount the drive and store it in a secure place.

Step 6 – Move the Keys to the Yubikey

Okay, we’re almost in the home stretch. Now we need to insert the Yubikey and move the keys over.

$ gpg --card-edit

Application ID ...: D2760001240102010006055532110000
Version ..........: 2.1
Manufacturer .....: unknown
Serial number ....: 05553211
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Private DO 1 .....: [not set]
Private DO 2 .....: [not set]
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

The default PIN codes are 123456 and 12345678. We’re not going to change them just yet. I prefer to change them at the end so I don’t constantly have to key in the admin PIN.

We can start by customizing the card:

gpg/card> name
Cardholder's surname:
Cardholder's given name: Phikshun

gpg/card> lang
Language preferences: en

gpg/card> login
Login data (account name): phikshun@example.com

gpg/card> (Press Enter)

Application ID ...: D2760001240102010006055532110000
Version ..........: 2.1
Manufacturer .....: unknown
Serial number ....: 05553211
Name of cardholder: Phikshun
Language prefs ...: en
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: phikshun@example.com
Private DO 4 .....: [not set]
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> quit

Now let’s move the keys.

$ gpg --edit-key $KEYID

Secret key is available.

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: ultimate
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
sub  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never       usage: A
[ultimate] (1). Phikshun <phikshun@example.com>

gpg> toggle

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> key 1

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb* 4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]

Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0xBECFA3C1AE191D15, created 2016-05-24

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb* 4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> key 1

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> key 2

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb* 4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> keytocard
Signature key ....: 07AA 7735 E502 C5EB E09E  B8B0 BECF A3C1 AE19 1D15
Encryption key....: [none]
Authentication key: [none]

Please select where to store the key:
   (2) Encryption key
Your selection? 2

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0x5912A795E90DD2CF, created 2016-05-24

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb* 4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> key 2

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> key 3

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb* 4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
(1)  Phikshun <phikshun@example.com>

gpg> keytocard
Signature key ....: 07AA 7735 E502 C5EB E09E  B8B0 BECF A3C1 AE19 1D15
Encryption key....: 6F26 6F46 845B BEB8 BDF3  7E9B 5912 A795 E90D D2CF
Authentication key: [none]

Please select where to store the key:
   (3) Authentication key
Your selection? 3

You need a passphrase to unlock the secret key for
user: "Phikshun <phikshun@example.com>"
4096-bit RSA key, ID 0x3F29127E79649A3D, created 2016-05-24

sec  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never
ssb  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
ssb* 4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never
                     card-no: 0006 05553211
(1)  Phikshun <phikshun@example.com>

gpg> save

Now our keys have been moved to the card (as indicated by “ssb>”):

$ gpg --list-secret-keys
/home/user/.gnupg/secring.gpg
-------------------------------
sec   4096R/0xFF3E7D88647EBCDB 2016-05-24
      Key fingerprint = 011C E16B D45B 27A5 5BA8  776D FF3E 7D88 647E BCDB
uid                            Phikshun <phikshun@example.com>
ssb>  4096R/0xBECFA3C1AE191D15 2016-05-24
ssb>  4096R/0x5912A795E90DD2CF 2016-05-24
ssb>  4096R/0x3F29127E79649A3D 2016-05-24

Step 7 – Change the PIN Codes

There are two PINs. The first PIN is 6-digits and it’s known as the user PIN. You will need to type it in when you use your keys (when logging in via SSH for example). Don’t pick something like 111111 or 123123. Randomly generate it and remember it. It’s only 6-digits.

The second PIN is 8-digits and it’s called the administrative PIN. It’s used to add or modify keys, change card settings or reset the card lock if you get the user PIN wrong too many times.

Change the PIN codes using the commands:

$ gpg --change-pin

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? q

Step 8 – Save Your Public Key

Finally, insert a plain old USB key (something FAT formatted) and copy your public key to it:

$ gpg --armor --export $KEYID > /mnt/public-usb-key/pubkey.txt

As implied by the name, the public key can be shared. If you’re using it for email encryption, you might want to upload it to a key server so that others can find it too.

You can now shutdown Tails. We won’t need it for the next part.

SSH and Git Signing

If you’re still reading then congratulations. You are a trooper. But now that we’ve gone through this process, how do we use our new key?

I use a Mac, so I’m going to walk through the process on macOS. If you’re running Windows or Linux, don’t despair. GPG works on those platforms too but the installation process will be different. There are plenty of guides on the Internet that have installation instructions. If you are using Windows, note that you should use GPG modern. GPG4Win does not support the Yubikey at this time.

To install GPG for macOS, download and install GPGSuite. It’s a quick install and it just works.

Once you have GPGSuite installed, open Terminal to import your public key and mark it as trusted:

$ gpg --import /Volumes/Key/pubkey.txt
gpg: key 0xFF3E7D88647EBCDB: public key "Phikshun <phikshun@example.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

$ gpg --edit-key 0xFF3E7D88647EBCDB

Secret key is available.

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: unknown       validity: unknown
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
sub  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never       usage: A
[ unknown] (1). Phikshun <phikshun@example.com>

gpg> trust
pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: unknown       validity: unknown
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
sub  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never       usage: A
[ unknown] (1). Phikshun <phikshun@example.com>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

pub  4096R/0xFF3E7D88647EBCDB  created: 2016-05-24  expires: never       usage: SC
                               trust: ultimate      validity: unknown
sub  4096R/0xBECFA3C1AE191D15  created: 2016-05-24  expires: never       usage: S
sub  4096R/0x5912A795E90DD2CF  created: 2016-05-24  expires: never       usage: E
sub  4096R/0x3F29127E79649A3D  created: 2016-05-24  expires: never       usage: A
[ unknown] (1). Phikshun <phikshun@example.com>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> quit

Now let’s setup SSH to use our smart card:

$ cat << EOF > ~/.gnupg/gpg-agent.conf
default-cache-ttl 60
max-cache-ttl 120
pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac
enable-ssh-support
write-env-file
EOF

$ killall gpg-agent
$ /usr/local/MacGPG2/bin/gpg-agent --daemon

That’s it! Now insert your Yubikey, and type:

$ ssh-add -L
ssh-rsa AAAAB4NzaC1yc2EAAAADAQABAAACAz[...]zreOKM+HwpkHzcy9DQcVG2Nw== cardio:000605553211

That’s your public key. You can set it up as an authorized key on any SSH server you like. If you’re in a devops shop, you (or your ops people) can distribute it with Chef/Ansible/Puppet. You can also log into Github and add it as a trusted SSH key (be sure to remove your insecure software keys while you’re at it).

To test, try logging into Github via SSH. When you login, you’ll receive the following prompt:

ssh

Finally, let’s setup Git signing. It’s as simple as turning on a few Git variables:

$ git config --global user.signingkey FF3E7D88647EBCDB
$ git config --global commit.gpgSign true

For details on validating commits and other options, see the documentation.

Conclusion

So let’s look at Alexsey Belan’s TTPs one more time:

  • He identified peripheral web servers via Google and Linkedin searches
  • Used known WordPress flaws and custom bugs to compromise PHP sites
  • Linux authentication mechanisms were altered to capture credentials [fixed]
  • Nmap was used to identify exposed network services internally
  • Corporate Wikis revealed administrative workflows and VPN details
  • Ticketing, bug tracking, and version control systems provided secrets (e.g. cryptographic keys, seeds, hashes, credentials, and source code) [fixed]
  • Cookies from weak non-production instances (e.g. staging) were valid in production as cryptographic materials were the same — bypassing 2FA
  • Client certificates (exposed by email, ticketing, or lifted from filesystems) were combined with known credentials to access corporate VPNs [fixed]
  • Engineering credentials were used to commit backdoors to version control which were self-approved and later deployed into production [fixed]

Not bad for a days work, eh?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s