Interactive jobs using ssh

From EGEE-see WIki

Jump to: navigation, search

Contents

Introduction

Although ssh is usually used as direct (client->server) shell, with some tricks it is possible to use it as a reverse shell too (client<-server). This means that the client needs to listen on a port instead of connecting to the server. At the same time, server needs to connect to the client instead of listening on a port.

Usage

The solution on the client side is somewhat simpler, using ProxyCommand option client can be instructed to use a pipe for connecting to the server instead of a direct network connection. The other end of the pipe is then connected to a process responsible for establishing the connection to the server itself. For the purpose of establishing a reverse shell, netcat is sufficient:

 $ ssh -vvv -o ProxyCommand="nc -l -p 2000" user@host

This command causes ssh client to start nc listening on the TCP port 2000 of the local machine. When the server connects to this port, pipes between ssh and nc will be used to pass data.

 ssh <--pipes--> nc <--network--> sshd

On the other end, sshd server has to start a connection to the nc instead of listening for a connection. For this to work, sshd needs to be started in inetd mode (-i option). In this mode sshd expects a connection with the client to be already established on the standard input. For this purpose a simple perl script can be used:

 #!/usr/bin/perl -w
 
 use strict;
 use Socket;
 
 my ($remote,$port, $iaddr, $paddr, $proto);
 
 $remote  = shift || die "No hostname given";
 $port    = shift || die "No port given";  # random port
 
 if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
 die "No port" unless $port;
 
 $iaddr = inet_aton($remote) || die "no host: $remote";
 $paddr = sockaddr_in($port, $iaddr);
 
 $proto = getprotobyname('tcp');
 socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
 connect(SOCK, $paddr) || die "connect: $!";
 
 open STDIN, ">&SOCK";
 open STDOUT, ">&SOCK";
 close SOCK;
 
 exec @ARGV;

The script connects to the hostname and port given on the command line and duplicates the connected socket to standard input and output. In the end a designated command is started, in our case the command is sshd in inetd mode:

 $ ./nc.pl home.irb.hr 2000 /usr/sbin/sshd -i

Now the connection between sshd and ssh can be established, but there still remains the problem of authentication. Just like in the normal ssh connection, client first needs to authenticate the server. Server authentication is based on the host keys and is easy to solve using a special configuration file. Configuration file needs to ensure that the host keys are accessible to the sshd since it is running as non-root user. As for the user authentication, public keys are used because standard authentication mechanisms (e.g. passwords) are not available. Taking all this into account, sshd_config should look like this:

 # Package generated configuration file
 # See the sshd(8) manpage for details
 
 # What ports, IPs and protocols we listen for
 #Port 22
 # Use these options to restrict which interfaces/protocols sshd will bind to
 #ListenAddress ::
 #ListenAddress 0.0.0.0
 Protocol 2
 # HostKeys for protocol version 2
 HostKey /home/vvidic/grid/rssh/rssh/ssh_host_rsa_key
 #Privilege Separation is turned on for security
 UsePrivilegeSeparation no
 
 # Lifetime and size of ephemeral version 1 server key
 KeyRegenerationInterval 3600
 ServerKeyBits 768
 
 # Logging
 SyslogFacility AUTH
 LogLevel QUIET
 
 # Authentication:
 LoginGraceTime 0
 PermitRootLogin no
 StrictModes no
 
 RSAAuthentication no
 PubkeyAuthentication yes
 AuthorizedKeysFile /home/vvidic/grid/rssh/rssh/authorized_keys
 
 # Don't read the user's ~/.rhosts and ~/.shosts files
 IgnoreRhosts yes
 # For this to work you will also need host keys in /etc/ssh_known_hosts
 RhostsRSAAuthentication no
 # similar for protocol version 2
 HostbasedAuthentication no
 # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
 #IgnoreUserKnownHosts yes
 
 # To enable empty passwords, change to yes (NOT RECOMMENDED)
 PermitEmptyPasswords no
 
 # Change to yes to enable challenge-response passwords (beware issues with
 # some PAM modules and threads)
 ChallengeResponseAuthentication no
 
 # Change to no to disable tunnelled clear text passwords
 PasswordAuthentication no
 
 # Kerberos options
 #KerberosAuthentication no
 #KerberosGetAFSToken no
 #KerberosOrLocalPasswd yes
 #KerberosTicketCleanup yes
 
 # GSSAPI options
 #GSSAPIAuthentication no
 #GSSAPICleanupCredentials yes
 
 X11Forwarding yes
 X11DisplayOffset 10
 PrintMotd no
 PrintLastLog yes
 TCPKeepAlive yes
 #UseLogin no
 
 #MaxStartups 10:30:60
 #Banner /etc/issue.net
 
 UsePAM no
 Subsystem sftp /usr/lib/openssh/sftp-server

For this configuration to work the relevant files need to exist (HostKey with the server host key and AuthorizedKeysFile with the user public key). Also most of the configuration options requiring root privileges are disabled (Port, UsePAM). At the same time public key authentication is enabled (PubkeyAuthentication option). If the relevant files are located in the current directory, the following script can be used to fix the configuration file with their correct locations and then start sshd:

 #!/bin/sh
 
 perl -pi -e "s|^HostKey.*|HostKey $PWD/ssh_host_rsa_key|;" \
     -e "s|^AuthorizedKeysFile.*|AuthorizedKeysFile $PWD/authorized_keys|;" \
     sshd_config
 
 for sftp in /usr/lib/openssh/sftp-server \
             /usr/libexec/openssh/sftp-server; do
 
     if [ -e $sftp ]; then
        perl -pi -e "s|^Subsystem.*sftp.*|Subsystem sftp $sftp|" sshd_config
        break
     fi
 done    
 
 exec ./nc.pl $@ /usr/sbin/sshd -Ddde -i -f $PWD/sshd_config

Now this script can be run with hostname and port where the client ssh/nc is running:

 $ ./run.sh home.irb.hr 2000

Conclusion

Reverse ssh technique is quite powerful as all the usual ssh features can be used: remote shell, file transfer and port forwarding (including X forwarding). Multiple streams can be opened to the destination if the ControlMaster and ControlPath options available in newer ssh version are used.

There are also several possible problems with this approach. First of all, sshd and perl need to be available on the WN, but this is usually not an issue. Next, the correct username needs to be used when starting ssh since sshd isn't running as root and can't switch user identities. Also, the sshd part can sometimes fail if it needs to run some actions available only to root (switching users, changing ownership of files etc.)

References

Personal tools