ssh-agent security
Michael A Stevens
mstevens at cmu.edu
Tue Aug 21 10:23:35 EST 2007
ssh-agent is a great tool that is often misconfigured with respect to
agent forwarding. How many people running ssh-agent and doing a ssh
-A have the very same public keys in ~/.ssh/authorized_keys of the machine
they are coming from? ssh(1) is very clear in its warning about enabling
agent forwarding. The simple act of prompting the user before using the
key would enable them to determine when they key was potentially being
used without their knowledge. It won't stop an attacker from riding on
ssh sessions that a user legitimately forms, but it will help deter
them from using the agent socket to make new ones either to other
machines or back to the source machine. This patch is by no means
ready to roll out to users, but any comments on it would be appreciated.
Usage:
patch -p0 < openssh-4.6p1-agentmod2.diff
cd openssh-4.6p1
./configure && make
./ssh-agent -di "xmessage -buttons Yes:0,No:1 Authorize key use by process with PID ="
(In other shell...)
SSH_AUTH_SOCK=/tmp/ssh-XXXXXXX/agent.XXXX; export SSH_AUTH_SOCK;
echo Agent pid XXXX;
ssh-add ~/.ssh/id_dsa
ssh -A user at host
ssh user at source
Mike Stevens
-------------- next part --------------
--- openssh-4.6p1/ssh-agent.c 2007-02-28 05:19:58.000000000 -0500
+++ openssh-4.6p1-agentmod2/ssh-agent.c 2007-08-20 19:56:38.000000000 -0400
@@ -134,6 +134,9 @@
/* Default lifetime (0 == forever) */
static int lifetime = 0;
+static int run_inform = 0;
+char inform_cmd[MAXPATHLEN];
+
static void
close_socket(SocketEntry *e)
{
@@ -247,6 +250,28 @@
MD5_CTX md;
Key *key;
+#if defined(SO_PEERCRED)
+ if (AUTH_CONNECTION == e->type) {
+ struct ucred cred;
+ socklen_t len = sizeof(cred);
+ char inform_cmdline[MAXPATHLEN];
+
+ if (run_inform && getsockopt(e->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
+ int ret;
+
+ snprintf(inform_cmdline, sizeof inform_cmdline, "%s %d",
+ inform_cmd, cred.pid);
+ ret = system(inform_cmdline);
+ if (ret != 0) {
+ close_socket(e);
+ return;
+ }
+ }
+ }
+#endif
+
+
+
buffer_init(&msg);
key = key_new(KEY_RSA1);
if ((challenge = BN_new()) == NULL)
@@ -314,6 +339,26 @@
Buffer msg;
Key *key;
+#if defined(SO_PEERCRED)
+ if (AUTH_CONNECTION == e->type) {
+ struct ucred cred;
+ socklen_t len = sizeof(cred);
+ char inform_cmdline[MAXPATHLEN];
+
+ if (run_inform && getsockopt(e->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
+ int ret;
+
+ snprintf(inform_cmdline, sizeof inform_cmdline, "%s %d",
+ inform_cmd, cred.pid);
+ ret = system(inform_cmdline);
+ if (ret != 0) {
+ close_socket(e);
+ return;
+ }
+ }
+ }
+#endif
+
datafellows = 0;
blob = buffer_get_string(&e->request, &blen);
@@ -1007,6 +1052,7 @@
fprintf(stderr, " -d Debug mode.\n");
fprintf(stderr, " -a socket Bind agent socket to given name.\n");
fprintf(stderr, " -t life Default identity lifetime (seconds).\n");
+ fprintf(stderr, " -i cmd Command to run on new connection.\n");
exit(1);
}
@@ -1047,7 +1093,7 @@
init_rng();
seed_rng();
- while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cdksa:i:t:")) != -1) {
switch (ch) {
case 'c':
if (s_flag)
@@ -1070,6 +1116,10 @@
case 'a':
agentsocket = optarg;
break;
+ case 'i':
+ run_inform = 1;
+ snprintf(inform_cmd, sizeof inform_cmd, "%s", optarg);
+ break;
case 't':
if ((lifetime = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid lifetime\n");
More information about the openssh-unix-dev
mailing list