DæmonNews: News and views for the BSD community

Daemon News Ezine BSD News BSD Mall BSD Support Forum BSD Advocacy BSD Updates

Understanding OpenSSH

By Saad Kadhi

OpenSSH (http://www.openssh.org) offers powerful features that allow fine- grained operation and access control when using RSA or DSA key pairs such as:
  • controlling port-forwarding (TCP or X11): denying port-forwarding for some specific keys while permitting only specific ports to specific hosts to be forwarded
  • associating a command to a key
  • tying keys to specific hosts: a user is only allowed to authenticate with a given key when coming from specific hosts

    The following article will go through some of these features, controlled by the authorized_keys file or whatever file the "AuthorizedKeysFile" keyword in sshd_config points to. The examples used in this article have been tested on OpenSSH 3.9 and OpenBSD 3.6. However, they should work just about the same with the portable version of OpenSSH available on other Unix-like and Linux operating systems.

    The authorized_keys file

    The file "authorized_keys", used on a per-user basis, lets you specify the RSA or DSA keys allowed to authenticate as a specific user. This file consists of one or more RSA or DSA public keys, one per line. Here is an example:
    ttypa:foo@eek> cat /home/foo/.ssh/authorized_keys
    ssh-dss AAAAB3NzaC1kc3MAAAEBAObMKlu5Clf6wvUzCglaXB\
    wcrfSoVGUZAMK54xDx95T7reXsmq18wZbmCPWB5VXWP3d9v2FG\
    BNwMotSrrbjwWq+tDBExiQI/osgIKnMcwRsU04ZW1tLNPD57vg\
    oI8EbDU95m7tUbyCSHA9LXZhNX4kEMDbDaZiiTwj9oTE0+UMl/\
    H9lj8Rvamrt3uKRMOGsULN3UhV3Bj9o6/Utl25IQGH9128+QBg\
    +1sQ1+4HUyeF8g8BkfVhl08l9DWDpKN7vKJxae+AaSLqPRCwM8\
    JUYArfvu1thbuRpmVV0AhGdHxmOLY8GbdSAQ3A7L+d0Dm+ZVug\
    9bVkHwZY7W4e9Immdw9fUAAAAVALNB86qZCuZ5ZiRXprjYsDIh\
    xRhfAAABAE8E+BNm/ocwtXBbv36omT3Ae79wSAq4VctZQ3wLQV\
    +fWdsD0z6S2qVbKMStSfcf8/qAPa43WCgT3VnzbX7iNM5gMyrw\
    py/GY71uZS/4DHDb7xXhsislyqCMWqM8tF5E0+oGCtd9WoISl0\
    NBxeJ8gzWNKipgm/aGiaHA6dkQ+qPBOoVXtPPJJVpetuHwmxWb\
    SqdLCxIqi2ecPTli1X7iyseDVoEw+xk7bBrSCDVmvSR4c1oVpx\
    4SXxgmFbtrTHP04VCkGjGAjJ65jTV84HJBnFw3HJD3KGZd8keu\
    NCI1OPYe5j0DQf50XpEPNVHSU6Jexxpea0T1Ne/MflUKsLgviN\
    AAAAEBALUTGCm0B4rUWeCRt5qdi3/zxww14LigJxSDonLtBkpY\
    +fFeYDePO9zchJ0N8J9be+7yrImwGbclwvAPcfOUTiVJDjyx9Q\
    kQt28FprVMktUHMW3Xsgii9adMmPH3OuahPUgvsvYak50qCoyy\
    QzqF+z7qPHmuUIA1BRIMpmHgYpBCBZN3YMnkgGNfve1mGoFrmE\
    zDg+sKbdVOmOrXYym+RU89yJqXM22vmMKuIvXATXm1oepzjLYr\
    NvXsnI9hil1k2QWfhtpxStcegJl8gJEmeSJqJ3o+6MJTwHDO2U\
    z78+KtTEDZvhr9zC3K8wcWl80KBVfA7NcYdEbjkMj47sOBzNc=\
     DSA 2048 key
    
    Note that this file is shown broken into multiple lines for display purposes. In reality, it is one line as shown below: ssh-dss <2048 bit key> DSA 2048 key

    Options associated with a given key are packed in at the beginning of the line corresponding to the key. From now on, we will show this as follows: ssh-dss AAAAB3NzaC... DSA 2048 key

    In the above example, a user can access machine "eek" as user "foo" if he/she has the private key associated with the DSA public key shown above.

    Once a user authenticates using the right key, he/she can (among other things):

  • request a pty (remote terminal session),
  • copy files back and forth using "scp" or "sftp",
  • use any command available on host "eek" as long as permissions allow her to do so,
  • forward X11 connections,
  • use local and remote forwarding.

    OpenSSH supports a number of options that enforce operation and access control. These per-key options consists of a comma-separated option specifications list where no white space is permitted, except within double quotes. Each option specification begins with a case-insensitive option keyword.

    Let's explore some of these options.

    Remote hosts

    In addition to public key authentication, we can limit hosts from where the user can connect from when using a specific key. This can be done using the 'from="pattern-list"' keyword.

    "pattern-list" is a comma-separated list of canonical names of the remote hosts a specific key may be used from to authenticate. The wildcards "?" and "*" are available. Moreover, remote hosts can be denied access if their canonical names are prefixed with the negation wildcard ("!").

    Yes, you guessed correctly, this option improves security by a small amount. If an intruder steals the key, he'll be able to log in from any host, as long as there is a route connecting that host to "eek". This option raises the bar since the intruder will have to compromise name servers and/or routers in order to use the stolen key.

    Here is an example:

    ttypa:foo@eek> cat /home/foo/.ssh/authorized_keys
    from="inka.myisp.com, !badhost.mycompany.com, *.mycompany.com" ssh-dss AAAAB... DSA 2048 Key 
    
    In the above example, a user using the key can only connect from "inka.myisp.com" and any machine in the ".mycompany.com" domain except "badhost.mycompany.com". Notice how the options preceed the key, all on one line.

    If a user attempts to connect from "badhost.mycompany.com", he is denied access . sshd generates the following log:

    Feb  1 09:31:37 eek sshd[3341]: Authentication tried for foo with
    correct key but not from a permitted host (host=badhost.mycompany.com,
    ip=192.168.1.34).
    
    Note that you can also use IP addresses: from="172.16.13.12,!192.168.1.34,192.168.1.*" ssh-dss AAAAB... DSA 2048 Key

    When using canonical names, sshd will make a DNS query unless a name appears in /etc/hosts and your resolver is instructed to use /etc/hosts before querying DNS.

    Commands

    It is also possible to associate specific commands with a key by using the 'command="some_command"' option. This option specifies that the command "command" must be executed whenever the key it is associated with is used for authentication. The command "some_command" is executed on a pty if the client requests it.

    Let's assume that user "foo" is an operator of some kind. The only thing she needs to perform on host "eek" is to run a backup script (we'll call it "/usr/local/scripts/eekbackup.sh").

    User "foo" can't log in from the local console. The only way he/she can access the system is from a remote machine through SSH using a DSA key pair. If we just paste the public key part to foo's authorized_keys file, he/she may access the system and run whatever command is available on "eek" if permissions allow her to do so. This is against our policy. We need to restrict the commands "foo" is authorized to execute so that the only command he/she can run is "/usr/local/scripts/eekbackup.sh". We do this by appending to her public key the following option specification: command="/usr/local/scripts/eekbackup.sh" ssh-dss AAAAB... DSA 2048 Key

    We can also prevent "foo" from getting a tty by adding the "no-pty" option specification: command="/usr/local/scripts/eekbackup.sh",no-pty ssh-dss AAAAB...\ DSA 2048 Key

    Three words of caution:

  • You can't chain commands by using several command option specifications. If there are several, the last one is used. If you need to run several commands, use a wrapper script.
  • The command option specification prevents the user from using something like "ssh foo@eek /path/to/some/command" to execute other commands. The user is only allowed to run the command specified in the option specification. The execution of this command is automatic.
  • Most of the security relies on the command/script access rights and clean coding.

    Port Forwarding

    While the 'command="command"' option restricts the commands a remote user is allowed to run upon authentication, it doesn't prevent her from using the SSH server as a mean to forward ports to other hosts using something like "ssh foo@eek -L 2222:badhost.mycompany.com:80". This applies only to local port forwarding.

    If we take the above-mentioned example, our security policy only allows the user authenticating as "foo" to run the backup script. She is not, for example, allowed to open connections to other hosts using port forwarding.

    The option "no-port-forwarding" prevents port forwarding such as any TCP/IP port forward request made by the client will return an error. This is often used with the 'command="command"' option. Well, let's put that in use: no-port-forwarding,command="/usr/local/scripts/eekbackup.sh",no-pty ssh-dss AAAAB... DSA 2048 Key

    Now, what if you want to allow only some ports to be forwarded? OpenSSH has an option for that too: 'permitopen="host:port"'. For example, you want to allow port forwarding to a remote imap server called "imap.myisp.com": permitopen="imap.myisp.com:143" ssh-dss AAAAB... DSA 2048 Key

    You can allow multiple host/port forwardings by using multiple "permitopen" options separated by commas.

    Note that no pattern matching is performed on the "host" part of the "permitopen" option specification. The specified hostnames must be known hostnames, domain names or IP addresses.

    If you attempt to forward a port that is not authorized, you will get a message like this: ttypa:plop@somehost> ssh foo@eek -L 8080:website:80 [snip] channel 5: open failed: administratively prohibited: open failed [snip]

    X11 Forwarding

    It is also possible to prevent a given key from using X11 forwarding. This is done using the "no-X11-forwarding" option specification: no-X11-forwarding,no-port-forwarding,command=\ "/usr/local/scripts/eekbackup.sh",no-pty ssh-dss AAAAB... DSA 2048 Key

    Of course, if you don't want to allow X11 Forwarding at all and for all users, it is far more simpler to do it in "sshd_config": X11Forwarding no

    Last but not least

    We have gone though some of the options available in OpenSSH to control operations and access. However these options don't replace a good firewall security policy to filter network access to your SSH servers.

    You must also make sure that the authenticating users can't modify the authorized_keys file's contents. I highly recommend to give the file to "root" and make it only readable for the user. And depending on your environment, you may also want to use the "uchg" and "uappnd" or "sappnd" flags with the "chflags" command on the authorized_keys file. That way, you make it more difficult to change its contents. And if you have used OpenSSH for some time, you'll notice that this file doesn't change often ;-).

    About The Author

    Saad Kadhi is a computer security consultant. In addition to computer security, his main areas of interest are Open Source and Unix Operating Systems. He is a member of the OpenBSD project. He can be reached at saad (at) docisland dot org.

    This document is Copyright (C) 2004 Saad Kadhi. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (FDL), Version 1.2 or any later version published by the Free Software Foundation; with the invariant sections being ``About the Author''.

  • Google
    Web daemonnews.org

    More Articles
  • Interview with Jan Schaumann
  • Interview with Theo de Raadt
  • Book Review: Virtualization with VMware ESX Server
  • Editorial: Not Quite Dead Yet
  • The Design of OpenBGPd
  • Interview with der Mouse
  • Letter to Steve Jobs
  • Interview with Manuel Bouyer on Xen
  • Apple and Open Source
  • BSDCan 2006
  • BSD Certification Survey Results
  • Lab in a Box
  • Ike Notes on BSDCan 2005
  • BSDCan 2005 Photos
  • FreeBSD Developer Summit Pictures

  • Advertisements




    Author maintains all copyrights on this article.
    Images and layout Copyright © 1998-2006 Dæmon News. All Rights Reserved.