Archivo

Entradas Etiquetadas ‘password’

Ocultar los parámetros de nuestro proceso a ps

Martes, 11 de Octubre de 2011 Gaspar Fernández Sin comentarios

password_flickrEn ocasiones, estamos desarrollando una aplicación, y ésta necesita que le pasemos como parámetro, por ejemplo, una contraseña. El gran peligro que esto tiene es que cualquier usuario, pidiendo un listado de procesos con ps podrá ver la contraseña.

Imaginemos que tenemos una aplicación (que hemos hecho nosotros) que conecta con un servidor, y dado que hemos hecho un script para automatizar el proceso, el nombre de usuario y contraseña los pasaremos como parámetro al ejecutable. Dicho proceso se llama “aplicacionsegura”, dicho programa lo hemos lanzado en un servidor y otros usuarios tendrán acceso a dicha máquina. Ahora uno de ellos ejecuta lo siguiente:

$ ps ax
….
10560 pts/3    S+     0:00 ./aplicacionsegura –user=usuario –passwd=micontraseña

¡Nuestro gozo en un pozo! Otro usuario ya tiene nuestra contraseña, y ha sido muy sencillo. Y además lo podremos ver (de hecho ps es lo que hace) viendo el archivo /proc/PID/cmdline. Aunque debemos ver qué opciones tenemos:

Modificar el parámetro passwd

Para ilustrar el ejemplo, vamos a fijar la posición de –passwd=xxxxx al segundo parámetro (la captura de parámetros no es objeto de este post). Lo primero que vamos a probar es introducir un terminador en las cadenas de los parámetros, Si la cadena empieza por ‘\0′ estará vacía:

1
2
3
4
...
argv[1][0]='\0';
argv[2][0]='\0';
....

Aunque tardaremos poco en darnos cuenta que da igual, por una parte, no podríamos borrar todos los rastros de información, ya que si escribimos en la posición 0 de la cadena “–passwd=micontraseña” un terminador, el resto de la cadena se quedará en memoria y podrá ser leída. De todas formas, la cadena parece que sólo tiene un espacio para ps, es más, el \0 le ha dado igual.

Probemos ahora escribiendo “HOLA” en la cadena de la contraseña (ahora sí pongo el código completo, test.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
  /* Reservamos memoria de sobra */
  char password[40];
  char usuario[40];

  if (argc<3)
    {
      fprintf(stderr,"Debe tener dos parámetros:\n%s --user=USUARIO --passwd=CLAVE\n", argv[0]);
      return EXIT_FAILURE;
    }

  /* Esto es un simple ejemplo, vamos a quitar --user y --passwd de una forma fea */

  /* Copiamos el usuario en otra variable */
  strcpy(usuario, argv[1]+7);   /* +7, para eliminar --user= (7 caracteres) */

  /* Copiamos la contraseña en otra variable */
  strcpy(password, argv[2]+9);  /* +9, para eliminar --passwd= (9 caracteres) */

  strcpy(argv[2]+9, "HOLA"); // EN LA CLAVE PONEMOS "HOLA"

  printf("user: %s ; pass: %s", usuario, password);
  /* Esperamos una tecla para terminar (sólo para que no se cierre demasiado rápido */
  /* y nos dé tiempo a mirar la información de ps */
  getchar();
  return EXIT_SUCCESS;
}

Ahora ejecutaremos lo siguiente:

$ gcc -o test test.c
$ ./test & # El programa test esperará una tecla para terminar, pero lo ejecutaremos de fondo, para que no se cierre.
$ ps ax
….
10809 pts/3 S+ 0:00 ./test –user=usuario –passwd=HOLA traseña
….
$ killall test # Para matar el proceso

Un efecto curioso, las cadenas de los parámetros no son NULL-terminated, de cara a /proc/PID/cmdline por lo que cuando ponemos un terminador, lo toma como un espacio. Y se ve parte del parámetro. Lo que sí podemos hacer es sustituir por asteriscos, tantos asteriscos como letras tenga el parámetro.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void rellenaConAsteriscos(char *cadena);

int main(int argc, char *argv[])
{
  /* Reservamos memoria de sobra */
  char password[40];
  char usuario[40];

  if (argc<3)
    {
      fprintf(stderr,"Debe tener dos parámetros:\n%s --user=USUARIO --passwd=CLAVE\n", argv[0]);
      return EXIT_FAILURE;
    }

  /* Esto es un simple ejemplo, vamos a quitar --user y --passwd de una forma fea */

  /* Copiamos el usuario en otra variable */
  strcpy(usuario, argv[1]+7);   /* +7, para eliminar --user= (7 caracteres) */

  /* Copiamos la contraseña en otra variable */
  strcpy(password, argv[2]+9);  /* +9, para eliminar --passwd= (9 caracteres) */

  rellenaConAsteriscos(argv[1]+7);
  rellenaConAsteriscos(argv[2]+9);

  printf("user: %s ; pass: %s", usuario, password);
  /* Esperamos una tecla para terminar (sólo para que no se cierre demasiado rápido */
  /* y nos dé tiempo a mirar la información de ps */
  getchar();
  return EXIT_SUCCESS;
}

void rellenaConAsteriscos(char *cadena)
{
  while (*cadena!='\0')
    *(cadena++)='*';
}

Ahora al ejecutar ps:

$ ps ax

10906 pts/3 S+ 0:00 ./test –user=******* –passwd=*************

Aunque esta forma revela en cierto modo la longitud de las contraseñas y el nombre de usuario, puede que no nos interese, que queramos eliminar el parámetro entero y que no se vea:

La manera rápida pero peligrosa y de andar por casa

El objetivo es escribir algo más largo que el último parámetro. Es decir, si el parámetro de contraseña tiene 22 letras, tenemos que escribir algo más grande, unas 23 letras, o cargarnos el terminador del segundo argumento (no son NULL-terminated, el kernel sabe dónde empieza y dónde termina la cadena, pero hay un NULL para comprobar que todo va bien).

En este caso podemos hacer:

1
strcpy(argv[2]+9, "Esto es una cadena muy grande para ver si cargándome el segundo parámetro desaparece toda la información");

y veremos cómo ps no nos dice nada, en principio no es demasiado elegante, nos estamos cargando un terminador, que nosotros podríamos necesitar, para lectura, y estamos escribiendo en una zona de memoria que no es nuestra, ya que el argumento tiene reservado un tamaño de memoria, y estamos escribiendo más de lo que debemos (podemos producir una violación de segmento).

Decirle al kernel que no queremos los parámetros

Parecida a la forma anterior, podemos hacer:

1
argv[2][strlen(argv[2])]=' ';

lo que no es intuitivo para nada, porque nos estamos cargando el terminador, que controla el paso de parámetros. De esta forma, no tendremos ningún parámetro. Tambén podemos hacer una forma general

1
argv[argc-1][strlen(argv[argc-1])]=' ';

De esta forma desaparecerán todos los argumentos de /proc/PID/cmdline ; sólo tendremos la ruta y el nombre del ejecutable, y nuestros datos, al menos por esta parte, estarán seguros.
Foto: marc falardeau (Flickr)

Hacer que konqueror conecte por FTP con los datos de .netrc ; Usar nombres de usuario que contienen arrobas

Martes, 20 de Julio de 2010 Gaspar Fernández Sin comentarios

Si usamos frecuentemente un archivo .netrc para almacenar nombres de usuario y contraseñas para servidores FTP, tal vez queramos utilizar esas mismas contraseñas para Konqueror sin necesidad de volver a escribirlas, ni almacenarlas en Kwallet (ya están en un sitio, ¿para qué meterlas en más lugares?). O tal vez se nos presente el siguiente problema, tenemos que conectar con un servidor FTP que permite conexiones anónimas, y al mismo tiempo el nombre de usuario (o la contraseña) que tenemos contiene el carácter arroba (@), tendríamos que meterlo en la barra de direcciones y al menos en KDE3.5.10 no nos deja hacerlo (no lo he probado en kde4), y la única forma rápida que se me ocurrió fue a través de .netrc.

Bien, si vamos a crear un archivo .netrc de primeras, leer esto, es un post de un proyecto que utilizaba .netrc para conectar donde se explica qué tiene que contener el archivo.

Luego editamos el archivo $HOME/.kde/share/config/kio_ftprc (si no existe lo creamos), por ejemplo con nano:

$ nano ~/.kde/share/config/kio_ftprc

e introducimos la siguiente línea:

EnableAutoLogin=true

Lo más fácil ahora es reiniciar KDE, pero yo opté por ejecutar lo siguiente:

$ dcopserver_shutdown
$ dcopserver

Como véis estoy utilizando dcop, esta solución es para KDE3, aunque supongo que para KDE4 habrá alguna solución sin usar dbus. Por otra parte, en mi sistema no uso KDE como gestor de ventanas, sólo utilizo algunas aplicaciones de KDE, por lo que no garantizo que se reinicie el gestor de ventanas.

Con esta solución, desde Konqueror pude abrir un FTP cuyo nombre de usuario contenía una arroba

Visita otras webs de la red