Ayer os enseñé a hacer uso del ttysnoop y ttysnoops para poder monitorizar sesiones de security shell (SSH). Uno de los puntos más molestos es que cada vez que hacemos uso del ttysnoop la aplicación nos consulta por el password de root. Y encima no podemos hacer uso de un script de "spawn/expect/send" para saltarnos este paso (ya lo he probado).
Parece ilógico, ¿verdad? Ya me he logueado como root para poder hacer uso de esta aplicación, ¿para qué voy a querer volverme a validar? Realmente lo que sucede es que a nivel de código fuente, dentro del config.h, se define a root como el usuario snoop predeterminado. Tras analizar el código del ttysnoops, entendí que esta solicitud de contraseña está puesta por mero capricho del programador.
En el bucle principal, a través del método authenticate, el programa crea un proceso hijo encargado de pedir al usuario la contraseña del usuario "snoop". A continuación he remarcado en rojo los valores de retorno y en verde el texto printado para solicitar el password del usuario. A primera vista el código asusta, pero veréis que es bastante inteligible.
311 void authenticate (int fd)
312 {
313 struct passwd *pw;
314
315 #ifdef SHADOW_PWD
316 struct spwd *spw;
317 #endif
318
319 int ret = 0;
320 char buff[16], *pwbuff;
321
322 if ((authpid = fork()) == 0) /* authentication child */
323 {
324 dup2 (fd, STDIN_FILENO);
325 dup2 (fd, STDOUT_FILENO);
326 dup2 (fd, STDERR_FILENO);
327 if (fd > STDERR_FILENO)
328 close (fd);
329
330 if ((pw = getpwnam(SNOOPUSER)) == NULL)
331 exit (1);
332
333 #ifdef SHADOW_PWD
334 if ((spw = getspnam(SNOOPUSER)) == NULL)
335 exit(1);
336 #endif
337
338 printf ("Connected to %s snoop server...\r\n", ptynam);
339 printf ("%s (ASCII %d) to suspend, %s (ASCII %d) to terminate.\r\n",
340 SC_STRING, SUSP_CHAR, TC_STRING, TERM_CHAR);
341 printf ("Snoop password:"); fflush (stdout);
342 if (inputs(buff, 16, stdin) == 0)
343 {
344 #ifndef SHADOW_PWD
345 if (strcmp(pw->pw_passwd, crypt(buff, pw->pw_passwd)) == 0)
346 #else
347 if (strcmp(spw->sp_pwdp, crypt(buff, spw->sp_pwdp)) == 0)
348 #endif
349 {
350 printf ("\r\nVerified OK... Snoop started.\r\n");
351 ret = 1;
352 }
353 else
354 printf ("\r\nPassword incorrect.\r\n");
355 }
356
357 fflush (stdout);
358 exit (ret);
359 }
360 }
En pocas palabras, el proceso ttyspoons crea un hijo para solicitar al usuario la contraseña de root. Este proceso verifica que el usuario root exista y que la contraseña sea válida para dicho usuario.
Ahora veamos el manejador del proceso padre, encargado de gestionar si la autenticación (realizada en el proceso hijo) ha sido correcta:
404 void sigchld (int sig)
405 {
406 int status, pid;
407 sig = sig;
408
409 if ((pid = wait(&status)) == authpid)
410 {
411 if (((status >> 8) & 0xff) == 1)
412 {
413 snoopfd = authfd;
414 fdmax = max(fdmax, snoopfd);
415 syslog (LOG_INFO, "snoop on %s (%s)", ttyname(STDIN_FILENO),
416 leafname(sockname));
417 }
418 else
419 close (authfd);
420
421 authpid = authfd = -1;
422 }
423 else if (pid == pgmpid)
424 raise (SIGHUP);
425
426 signal (SIGCHLD, sigchld);
427 }
Según el código de este manejador, para cumplir la verificación deberemos de hacer que el proceso hijo finalice con valor 1. Cualquier otro valor devolverá error de autenticación.
Visto esto, he modificado el método authenticate para que JAMAS DE LOS JAMASES se nos solicite la contraseña y que además la verificación del padre se pase de forma correcta:
357 void authenticate (int fd)
358 {
359 if ((authpid = fork()) == 0) /* authentication child */
360 {
361 dup2 (fd, STDIN_FILENO);
362 dup2 (fd, STDOUT_FILENO);
363 dup2 (fd, STDERR_FILENO);
364 if (fd > STDERR_FILENO)
365 close (fd);
366 exit(1);
367 }
368 }
Como veis el método ha adelgazado bastante... y encima funciona: Si eres root no te solicitará ninguna contraseña de usuario snoop, y si no eres root no podrás clonar ninguna terminal. Por cierto, si queréis recompilar las fuentes para Ubuntu o Debian, vais a tener que realizar las siguientes modificaciones.
No hay comentarios:
Publicar un comentario
Si te ha gustado la entrada o consideras que algún dato es erróneo o símplemente deseas dar algún consejo, no dudes en dejar un comentario. Todo feedback es bienvenido siempre que sea respetuoso. También puedes contactarme vía Twitter @Hamster_ruso si lo consideras necesario.