Hi there.

I was thinking about what an attacker could do with a preauth exploit from
their chroot, and it occurred to me that they might try ptrace'ing the
other preauth slaves.  If they could do this it would give them the
passwords for any other users without much effort:

$ sudo strace -p 30476
Process 30476 attached - interrupt to quit
[...]
write(4, "\0\0\0\20thisismypassword", 20) = 20

Now this doesn't work as the privsep user (EPERM on the ptrace attach)
on either OpenBSD or Linux, but I don't know if there's something
fundamental stopping it or I'm just doing something wrong.  There's a
decent chance it will work somewhere, though (Mac OS X?).

It's simple to encrypt the monitor->slave traffic (and cheap; a quick test
had the regress time actually go down a little, probably due to some
other factors).  This makes the traffic a lot less useful to an attacker:

Process 8432 attached - interrupt to quit
[...]
write(4, "\0\0\0\25\n", 5)              = 5
write(4, "\355\27\327\214%\372\263d2\215\2100\247\252=&\20\247\263"..., 20) = 20

So:

* It's cheap.  I picked rc4 beacuse it's simple to use and as it's a stream
  cipher there's no block padding issues, but it could be any cipher.

* It raises the bar against monitoring by an attacker if the preauth
  sshd is compromised (but if the attacker can ptrace the processes they
  could also recover the crypto keys/state).

* It protects against trivial monitoring by root (but root could trojan
  sshd anyway).

Do you think this is worth pursuing?


Index: monitor.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/monitor.c,v
retrieving revision 1.89
diff -u -p -r1.89 monitor.c
--- monitor.c	7 Nov 2006 10:31:31 -0000	1.89
+++ monitor.c	22 Jan 2007 02:12:19 -0000
@@ -1579,6 +1579,8 @@ monitor_init(void)
 		mm_init_compression(mon->m_zlib);
 	}
 
+	mm_init_encryption();
+
 	return mon;
 }
 
Index: monitor_wrap.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/monitor_wrap.c,v
retrieving revision 1.54
diff -u -p -r1.54 monitor_wrap.c
--- monitor_wrap.c	12 Aug 2006 20:46:46 -0000	1.54
+++ monitor_wrap.c	22 Jan 2007 02:12:19 -0000
@@ -30,6 +30,9 @@
 
 #include <openssl/bn.h>
 #include <openssl/dh.h>
+#include <openssl/rand.h>
+#include <openssl/rc4.h>
+#include <openssl/err.h>
 
 #include <errno.h>
 #include <pwd.h>
@@ -73,6 +76,26 @@ extern struct monitor *pmonitor;
 extern Buffer input, output;
 extern Buffer loginmsg;
 
+static int enc_enabled = 0;
+static RC4_KEY rc4;
+
+void
+mm_init_encryption(void)
+{
+        u_int i;
+        u_char seed[20];
+
+        debug3("mm_init_encryption");
+        if (RAND_bytes(seed, sizeof(seed)) <= 0)
+                fatal("mm_init_encryption: no random bytes available");
+
+        RC4_set_key(&rc4, sizeof(seed), seed);
+        /* discard early keystream */
+        for (i = 0; i <= 256; i += sizeof(seed))
+                RC4(&rc4, sizeof(seed), seed, seed);
+        enc_enabled = 1;
+}
+
 int
 mm_is_monitor(void)
 {
@@ -95,6 +118,8 @@ mm_request_send(int sock, enum monitor_r
 	buf[4] = (u_char) type;		/* 1st byte of payload is mesg-type */
 	if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
 		fatal("%s: write: %s", __func__, strerror(errno));
+	if (enc_enabled)
+		RC4(&rc4, mlen, buffer_ptr(m), buffer_ptr(m));
 	if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
 		fatal("%s: write: %s", __func__, strerror(errno));
 }
@@ -102,8 +127,8 @@ mm_request_send(int sock, enum monitor_r
 void
 mm_request_receive(int sock, Buffer *m)
 {
-	u_char buf[4];
-	u_int msg_len;
+	u_char buf[4], *payload;
+	u_int msg_len, plen;
 
 	debug3("%s entering", __func__);
 
@@ -119,6 +144,12 @@ mm_request_receive(int sock, Buffer *m)
 	buffer_append_space(m, msg_len);
 	if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
 		fatal("%s: read: %s", __func__, strerror(errno));
+	if (enc_enabled) {
+		/* first byte is message type which is not encrypted */
+		payload = buffer_ptr(m) + 1;
+		plen = msg_len - 1;
+		RC4(&rc4, plen, payload, payload);
+	}
 }
 
 void

