La idea viene de la forma de iniciar una conexión SSL a través del puerto 25 (conocido como STARTTLS). Cuando nos conectamos al puerto 25, para iniciar la conexión TLS, debemos enviar el comando STARTTLS en texto claro: A partir de entonces la conexión es cifrada.
Podemos definir un comando arbitrario, por ejemplo STARTSSH, para que a partir de entonces tome el control el daemon sshd para transformar la conexión en el puerto 25 en una conexión SSH.
Para añadir el comando deberemos hacer muy pocos cambios en el fichero qmail-smtpd.c:
--- netqmail-1.06/qmail-smtpd.c 2010-09-07 14:14:31.773951293 +0200 +++ netqmail-1.06-ssh/qmail-smtpd.c 2012-05-24 22:55:10.029940202 +0200 @@ -37,6 +37,8 @@ #include "wait.h" #include "fd.h" +#include "startssh.h" + /* start chkuser code */ #include "chkuser.h" /* end chkuser code */ @@ -330,6 +332,21 @@ if (!stralloc_0(&rcptto)) die_nomem(); out("250 ok\r\n"); } + +void smtp_startssh(arg) char *arg; { + unsigned long long_fd; + int fd; + char *fdstr; + //out("220 2.0.0 Ready to start SSH\r\n"); + flush(); + + if (!startssh()) + die_syserr(); + + /* reset SMTP state */ + seenmail = 0; +} + void smtp_starttls(arg) char *arg; { unsigned long long_fd; int fd; @@ -705,6 +722,7 @@ , { "noop", err_noop, flush } , { "vrfy", err_vrfy, flush } , { "starttls", smtp_starttls, flush } +, { "startssh", smtp_startssh, flush } , { 0, err_unimpl, flush } } ;
A continuación deberemos añadir la función startssh() que “spawneará” un sshd en modo inetd. En lugar de usar un socket usará stdin y stdout para comunicarse con el cliente (la parte de red ya esta establecida por el qmail). El fichero startssh.c sería:
#include "scan.h" #include "env.h" #include <unistd.h> int startssh(void) { unsigned long fd; char *fdstr; char *args[] = {"/usr/bin/sudo", "/usr/sbin/sshd", "-i", (char *) 0 }; return execv("/usr/bin/sudo", args); }
También deberemos añadir startssh.h para la definición de la función a incluir en el qmail-smtpd.c:
int startssh(void);
Deberemos añadir un sudo sin password para ejecutar el sshd, ya que qmail no se ejecura como root:
vpopmail ALL=(ALL) NOPASSWD: /usr/sbin/sshd
El servicio de daemontools sería como el siguiente:
#!/bin/sh . /var/qmail/ssl/env QMAILQUEUE="/var/qmail/bin/qmail-scanner-queue.pl" export QMAILQUEUE MAXSMTPD=`cat /var/qmail/control/concurrencyincoming` LOCAL=`head -1 /var/qmail/control/me` QMAILDUID=`id -u qmaild` NOFILESGID=`id -g qmaild` if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" -o -z "$LOCAL" ]; then echo QMAILDUID, NOFILESGID, MAXSMTPD, or LOCAL is unset in echo /var/qmail/supervise/qmail-smtpd/run exit 1 fi if [ ! -f /var/qmail/control/rcpthosts ]; then echo "No /var/qmail/control/rcpthosts!" echo "Refusing to start SMTP listener because it'll create an open relay" exit 1 fi /usr/local/bin/softlimit -m 100000000 \ /usr/local/bin/sslserver -e -n -v -R -l "$LOCAL" -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \ -u 89 -g 89 0 25 /usr/local/bin/rblsmtpd -b -rsbl.spamhaus.org \ /usr/local/src/netqmail-1.06-ssh/qmail-smtpd mail.systemadmin.es /home/vpopmail/bin/vchkpw /var/qmail/bin/qmail-smtp-auth-wrapper.sh 2>&1 7>&1
Podemos probar de ejecutarlo a mano para ver que funciona:
# /service/qmail-smtpd-ssh/run & [1] 32279 # sslserver: cafile 32288 sslserver: ccafile 32288 sslserver: cadir 32288 /usr/local/ssl/certs sslserver: cert 32288 /var/qmail/ssl/mail.systemadmin.es.crt sslserver: key 32288 /var/qmail/ssl/mail.systemadmin.es.key sslserver: param 32288 /var/qmail/ssl/dhparam 1024 sslserver: status: 0/20 # # telnet localhost 25 Trying 127.0.0.1... sslserver: status: 1/20 Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. sslserver: pid 32291 from 127.0.0.1 sslserver: ok 32291 mail.systemadmin.es:127.0.0.1:25 localhost:127.0.0.1::54007 220 mail.systemadmin.es ESMTP startssh SSH-2.0-OpenSSH_4.3 sslserver: end 32290 status 0 sslserver: status: 0/20 Protocol mismatch. Connection closed by foreign host.
Una vez habilitado el servicio desde un cliente cualquiera veríamos:
# telnet localhost 25 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. 220 mail.systemadmin.es ESMTP startssh SSH-2.0-OpenSSH_4.3 quit Protocol mismatch. Connection closed by foreign host.
Por lo que ahora deberemos modificar el cliente ssh para que ejecute el comando STARTSSH al iniciar la conexión contra el puerto 25. La modificación es simple, si lo hacemos sin ninguna opción que controle que se añada o no dicho comando especial:
--- sshconnect.orig 2012-06-14 19:18:20.220820357 +0200 +++ sshconnect.c 2012-06-14 19:13:00.930746433 +0200 @@ -415,6 +415,8 @@ debug("Connection established."); + write(sock,"startssh\n",sizeof("startssh\n")); + /* Set SO_KEEPALIVE if requested. */ if (want_keepalive && setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
Con el cliente modificado ya podemos hacer conexiones en el puerto 25 como si se tratase de únicamente de un SSH:
# ./ssh systemadmin.es -p 25 -l jordi jordi@systemadmin.es's password:
Una vez conocido el comando STARTSSH ya no tiene gracia, por lo que idealmente el comando debería ser alguna cadena aleatoria, o por ejemplo para complicarlo más, dependiente de la hora.
Por otro lado, este patch puede ser usado como backdoor únicamente cambiando /usr/sbin/sshd por /bin/bash.
No hay comentarios:
Publicar un comentario
Nota: solo los miembros de este blog pueden publicar comentarios.