SSHARK !

DNS-based expiration and revocation of SSH client keys

sshark-29c3.pdf

The goal of SSHARK is to allow the expiration and revocation of SSH client keys by putting information in DNS TXT records...

without creating any additional public key infrastructure,

creating any additional public key infrastructure, without having to run a special version of the SSH server, and

having to run a special version of the SSH server, and without having to actively manage authorized_keys files.

How is this possible? With SSHARK, information about SSH key validity is stored in DNS. The information is signed by the SSH key itself rather than with a separate certifying key. The validity check is performed on the server side by using the command="..." facility available in the authorized_keys file as supported by OpenSSH and DropBear SSH servers.

Quick start

SSHARK is meant to be simple to use. Here's a brief how-to. Be careful not to lock yourself out of your house. :-)

(1) Put sshark.pl somewhere on the sshd side and make it executable. Assure that you have the Perl modules Net::DNS and Authen::PAM in your library path.

(2) Put sshark-gen.sh in the ~/.ssh/ directory where you keep your SSH public and private keys, and make it executable. Assure that you have a base64 binary in your command path.

(3) Assure that the 'comment' in your SSH public key is in valid RFC822 email address form, with the domain part being a DNS zone where you have the ability to add records. (If this makes you scream "do not want!" then leave it alone, and specify the lookup domain explicitly with -d in your server-side invocation later.)

(4) Generate some expiration data. In the directory where your SSH public/private keys are stored, execute: ./sshark-gen.sh id_rsa 86400. You will be prompted for the passphrase to decrypt your SSH private key. If successful, the program will generate a batch of DNS RR's indicating that your key is valid for 1 day (86400 seconds) from the current system time. For example:ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com. TXT "sshark1 serial 1356743196 expiry 1365383196" s1356743196.ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com. TXT "sshark1 data L7MfKYu2Ok3zk95N/xuXkIiKfkk8xlR+Xcj7gK/wseXWx8EhtuKL36tzJfyVmVW2LQuvTVvH0oK2" s1356743196.ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com. TXT "sshark1 data VDx+rPDyQ47GnoJoXR589LOaMYTUzZF3Aq3EZ3dpB7z69mYWsL3utI9AX81rmUiDEWE0PqbGlZFQ" s1356743196.ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com. TXT "sshark1 data n7s7D2RaxLL7fIYnMOQ="

(5) Insert the DNS RR's into the appropriate DNS zone and ensure they are being served correctly.

(6) On the machine running sshd , add your SSH public key to your ~/.ssh/authorized_keys file if it's not already there. Preface the key with a "forced command" that invokes sshark.pl specifying the key type and fingerprint. For example:command="/home/nobody/bin/sshark.pl -t ssh-rsa -l be:6d:70:bf:04:e2:f8:65:2b:81:4a:72:9b:73:3c:ea" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDIISOnw1Ennf84oHyHNdNdmfHlAknHOecAHjRiIo4/3oi3vMV9O201257A8b34ntZOE6uquMiorogmkyWdYfsv0aX1vO3yDGRPd8/+bOb509vhZAcRvFaEYiN5dxgFeXGFsGH/1Zu1cee3MTcnRjk8HJMXpetvUpFoc/CZnrQw/w== nobody@example.com

(7) Test by trying to SSH into the system running sshd using the SSH key. A message from SSHARK will appear upon successful authentication, for example:[sshark] Your key is valid until Sat Dec 8 03:28:30 2012

(8) Test by generating revocation data with ./sshark-gen.sh id_rsa revoke and publishing it. Now try to SSH in, and your access should be denied with a message from SSHARK, for example:==========================[sshark]========================== Sorry, your SSH key has been revoked. Key: ssh-rsa be:6d:70:bf:04:e2:f8:65:2b:81:4a:72:9b:73:3c:ea Zone: nobody._sshark.example.com ============================================================

Server-side operational details

In this section, "SSHARK" refers to the server-side component, sshark.pl .

USAGE: sshark.pl [ -f <queryFile> ] [ -d <queryDomain> ] -t <keyType> -l <keyHash>

authorized_keys

command="..."

sshd

ssh-rsa

ssh-keygen(1)

SSHARK normally looks for expiration/revocation records pertaining to a given key (called claims) under a zone derived from that key's comment field. The zone is essentially the comment with the @ substituted with the domain component _sshark . For example, a key with comment nobody@example.com will cause SSHARK to look for records under nobody._sshark.example.com . Alternatively SSHARK can be told to look in a different zone using the -d flag. SSHARK always looks for these records by issuing DNS TXT queries. SSHARK can be told to look in a local file (in addition to DNS) by specifying the -f flag, which has a default value of /var/lib/sshark/sshark.dat . That file contains one record per line in whitespace-delimited key-value form, and must be readable by the authenticating user.

The records containing the claims themselves are named after the key type and fingerprint, appended with the zone name. For example: ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com This name is called the querybase. Each claim is a string in the format sshark1 serial S expiry E where S is a serial number (conventionally the UNIX epoch time of the creation of the record, but can be any monotonically incrementing value) and E is the UNIX epoch time of the key's expiration. If E is equal to 0 , the claim is one of total revocation.

Each claim is cryptographically signed by the SSH key to which it refers. The records containing the signature are named for the serial number of the claim, prepended with the letter s , and appended with the querybase. For example: s1356743196.ssh-rsa-be6d70bf04e2f8652b814a729b733cea.nobody._sshark.example.com . The signature records, when concatenated, contain a base64-encoded signed message containing the lower case hexadecimal representation of the SHA-256 hash of the claim.

SSHARK evaluates all claims available for a given key, starting with any revocation claims, and then proceeding through each claim in descending serial number order, until a valid claim is found. Invalid claims, such as those which are malformed or contain an invalid signature, do not affect SSHARK's final decision about key validity. If no valid claims are found, access is denied. If a valid revocation claim is found, access is denied. If a valid expiration claim is found, and the expiration date is not in the future according to the system clock, access is denied. When access is denied, SSHARK informs the authenticating user of the reason, the key fingerprint, and the relevant lookup zone, and terminates.

If access is not denied, SSHARK informs the authenticating user of the the expiration date of the key currently in use, and attempts to make things proceed as normal. If a command was requested, SSHARK executes it. If the internal SFTP facility was requested, SSHARK executes /usr/lib/sftp-server . If a shell was requested, SSHARK calls pam_start(3) with the service name sshark and then calls pam_open_session(3) . If /etc/pam.d/sshark is present, something like a normal login will take place. Otherwise, the user's login shell will simply be spawned in whatever environment was already prepared by sshd , which tends to be fairly complete already.

The code

SSHARK is currently available in a reference implementation that only supports ssh-rsa type keys. The server-side component is about 375 lines of Perl, and the component which generates the expiration/revocation data (claims) is a small Bash script. It is up to you to host the claims somewhere in DNS. There is also a pam.d(5) file recommended but not required for the server side. We consider the server-side component to be nearing production quality. However we call it a reference implementation because its dependence on various Perl modules and a recent version of ssh-keygen(1) makes it less than totally portable. Part of SSHARK's goal is to be deployable on SSH servers without the fuss of dependencies. A binary, even statically-linked if necessary, will eventually accomplish this in a way that the Perl script cannot.

You can download the 0.1.1 release tarball here: sshark-0.1.1.tar.gz

The files contained in the tarball are:

FAQ

Is SSHARK an oracle for attackers who want to know my usernames?

All of SSHARK's DNS records are named after 128-bit fingerprints, which makes them an unreasonable target for brute-force lookups. However DNS can be leaky for other reasons. Restrict AXFR access as always, and think about all the risks of storing any sensitive information in DNS.

All of SSHARK's DNS records are named after 128-bit fingerprints, which makes them an unreasonable target for brute-force lookups. However DNS can be leaky for other reasons. Restrict AXFR access as always, and think about all the risks of storing any sensitive information in DNS. Doesn't doing username-containing DNS lookups at every SSH authentication attempt constitute an information leak?

Maybe it does, depending on your environment. You don't have to use the comment field to determine your lookup zone; it can be overridden with the -d flag. This leaves the fingerprints, which are in most cases user-granular. Depending on your environment and needs, this might constitute an information leak.

Maybe it does, depending on your environment. You don't have to use the comment field to determine your lookup zone; it can be overridden with the flag. This leaves the fingerprints, which are in most cases user-granular. Depending on your environment and needs, this might constitute an information leak. What happens to previous claims of revocation/expiration? What about DNS caching?

A lookup may return multiple claims about the same SSH key. As long as the serial numbers of new claims increase monotonically, the newest claim will be evaluated first. Above that, revocations are sorted first, so a revocation will always override a claim of unreached expiration.

A lookup may return multiple claims about the same SSH key. As long as the serial numbers of new claims increase monotonically, the newest claim will be evaluated first. Above that, revocations are sorted first, so a revocation will always override a claim of unreached expiration. Why would anyone need this? OpenSSH is going to have built-in [insert feature here].

The purpose of SSHARK is to start managing the expiration and revocation of SSH client keys in the real world, where many systems will not run the latest version of OpenSSH any time soon, if ever.

The purpose of SSHARK is to start managing the expiration and revocation of SSH client keys in the real world, where many systems will not run the latest version of OpenSSH any time soon, if ever. What does SSHARK stand for?

SSHARK will stand for a little teasing, as long as it is well fed.

Future directions

Re-write everything in C and eliminate server-side dependence on ssh-keygen. While the Perl reference implementation is robust, it is less portable than we would like. One of the goals of SSHARK is to institute SSH key management even in the crufty corners of the net. Telling people to install Perl modules or have the latest ssh-keygen installed is a hindrance to widespread deployment.

While the Perl reference implementation is robust, it is less portable than we would like. One of the goals of SSHARK is to institute SSH key management even in the crufty corners of the net. Telling people to install Perl modules or have the latest installed is a hindrance to widespread deployment. Handle other SSH key types besides RSA. Many people use DSA keys, and ECDSA is the future.

Many people use DSA keys, and ECDSA is the future. Integrate DNS updates. Publishing the DNS records should be streamlined. Some DNS servers provide mechanisms for pushing updates. SSHARK should know about them.

Who's responsible for this?

SSHARK is the work of Greenhost, a growing technology company in Amsterdam. We are develping projects that promote digital security and freedom, and building hosting platforms that respect free speech and the environment. SSHARK was developed by by Anatole Shaw with crucial input from Sacha van Geffen and Mart van Santen. Thanks to Carl van der Tas for important early feedback on the 29c3 presentation, and to Douwe Schmidt for drawing the hilarious logo.

Please send feedback to Anatole Shaw, ash AT greenhost DOT nl.