karolszafranski.info

Linux geekiness taken professionally

One-Time Passwords on Debian Linux for SSH and VNC

2013-11-15 by Karol Szafrański, tagged as linux, otp, personalsec

Let's imagine your employer openly implements spyware on employees' computers as part of their DLP policy. Upon signing your contract you're warned that there is a program somewhere there that "monitors all user activity and could prevent some of it" and instructed that the attempts of killing, removing or tampering with the tool would be awarded with dismissal. They would log all visited websites, take screenshots at any time, and record all keystrokes. So every time you access your personal machine from work, you put your precious, lenghty, complex password (you have such one, right?) at risk of being recorded and stored in some audit database in plaintext for unspecified people to see.

Or maybe you are pretty comfortable with the security of the OS you're using but need to keep away a coworker/roommate/competitor spy looking over your shoulder, either directly or by some sophisticated means?

I came across a similar issue some time ago. And people around carrying RSA SecurID tokens made me wonder. So, let's render a captured SSH password useless.

HOWTO: Linux remote desktop with hardware token authentication at zero cost with mOTP

Initial state: A Debian server machine, with remote access via SSH. A Linux/Windows/MacOS box at the end, optionally with a need to access X11 desktop session on the other end as simply as possible.

Solution: Deploy one-time password authentication on the server for SSH connections using mOTP. Use a scripted x11vnc to share desktop session and presetted SSVNC as a client.

Token device setup (I'll use Android phone with mOTP app as an example but mOTP supports dozens of devices and systems, not only for phones)

  1. Install mOTP on the phone. A preferred way in my case would be F-Droid since I don't use Google Play store.
  2. Open the app. Create a "mOTP" profile, making up a 20-character seed.
  3. A random secret will be generated. Press and hold the profile to see "View secret" option - you'll need that later

Server configuration steps (tested on Debian Wheezy, execute all as root):

  1. Install libpam-script from the repo. It contains the necessary PAM module.
  2. mkdir /etc/otp; mkdir /etc/otp/cache
  3. Download http://motp.sourceforge.net/PAM-script.zip and put otp-auth and otp-secrets to /etc/otp. Don't forget to set owner:group to root:root
  4. chmod 600 /etc/otp - files here are more sensitive than your /etc/shadow file as we'll put plaintext secrets there!
  5. chmod 700 /etc/otp/cache
  6. ln -s /etc/otp/otp-auth /usr/share/libpam-script/pam_script_auth - to satisfy requirements hardcoded into PAM module
  7. chmod 711 /etc/otp/otp-* - the module accepts no other permissions combination
  8. Edit /etc/otp/otp-auth: set install_dir variable: my $install_dir = '/etc/otp/';
  9. Edit /etc/otp/otp-secrets: replace "testuser" with your account name, set secret to the value read from the token app above and make up a PIN. Every user that ought to log in with SSH must now have an entry here!
  10. Edit /etc/pam.d/sshd: find "# Standard Un*x authentication.", comment out "@include common-auth" and add pam_script call:
    # Standard Un*x authentication.
    # @include common-auth
    auth required pam_script.so onerr=fail dir=/usr/share/libpam-script
    	

From now on, all your login attempts via SSH require token generated with the token app instead of password. Local console logins are unaffected - they still use existing, static passwords as this configured in /etc/pam.d/login. If something does not work, look at /var/log/auth.log and check the file ownership/permissions.

Now, the remote desktop part: One-click SSVNC configuration

  1. Install x11vnc on the server
  2. Create a script for the user, eg. /home/joe/bin/remote.sh
    #!/bin/bash
    
    # clean up after previous session
    killall x11vnc
    
    x11vnc -display :0 -geometry 1280x1024 -listen 127.0.0.1 -rfbport 5899
    # -display :0 - over ssh, x11vnc will not autodetect which X display to hook to
    # -geometry 1280x1024 - force the screen resolution in case the autodetection fails
    # -listen 127.0.0.1 - SSH will let us connect to loopback with port forwarding
    # -rfbport 5899 - I picked this one as default 5900 interfered with libvirt/KVM consoles
    
    #  Wait for x11vnc to fully start accepting connections.
    #  From my experiments 3 sec is more than enough
    
    sleep 3
    
  3. Install (ie. download and unzip) SSVNC on the client
  4. Configure the connection parameters:

    Note a non-default SSH port 22000. Just omit this to use a default 22.
  5. Voila - now you can hit Connect (or save a preset file you can pass to SSVNC as a parameter, thus making a 1-click solution)

SSH's tunelling feature is a necessary wrap-up for VNC, which is unencrypted by default. A benefit of tunnelling is that you only have to enable and properly secure only one external service. As we speak on it: I had taken a lesson of changing default SSH port long ago - first time I enabled port 22 on a machine, it took some bots from Chinese IP space only five hours to realize that and make an initial scan with popular usernames like root, admin, apache, wwwdata, pgsql etc. Additional layer of fail2ban or portknocking won't hurt as well.

Two-factor authentication, anyone?

Till now I haven't found a simple and elegant method to enhance the above to a real 2FA using mOTP with local accounts (I haven't explored any mOTP+LDAP options). But I have a quick-and-dirty concept: once paired with a standard VNC server (providing separate X sessions) instead of x11vnc you could make an actual 2FA; it's only a matter of setting something useless as a login shell. Once the user authenticates herself with a token, they connect via VNC and are presented with a login screen waiting for a standard, local PAM password. No extra sctipt needed in this case. If I ever test it and come to any usable results, I'll add them here.