En este nivel nos proporcionan lo siguiente:
«There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?»
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();</p>
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);</p>
system("/usr/bin/env echo and now what?");
}
Recordando C, aplicando llamadas en sistemas GNU\Linux
stdlib.h
- Conversión, memoria, control de procesos, ordenación y búsqueda, matemáticas.
- abort
- exit
- atexit
- getenv
- system
unistd.h
- Header que provee acceso al API POSIX de los sistemas operativos GNU\Linux \ Unix.
- POSIX: Portable Operating System Interface (standard/portabilidad).
- Es parte de la C POSIX library, junto con assert.c, limits.h, stdarg.h, stdio.h, etc)
- Es una interfaz para las syscalls
string.h
- Manejo de cadenas, strcpy,strcmp,etc
sys/types.h
- Funciones de búsqueda y ordenamiento de directorios y manipulación de archivos
stdio.h
- Funciones de entrada/salida
Un programa en C siempre comienza con la llamada a la funcion main(), siendo la primera funcion que se ejecuta cuando corremos un programa.
El tipo de retorno que nos da el programa será int ( 0 ) si se ha producido con éxito, cualquier otro valor de retorno de la funcion main() que no sea 0 significa algún tipo de error.
Esta funcion main() acepta 3 argumentos:
int main(int argc, char **argv, char **envp)
- int argc = nº de command line arguments
- **argv = lista de los command line arguments
- **envp = array de cadenas que representan las variables de entorno del usuario
Posteriormente, declaramos los tipos de las variables gid_t y uid_t y las seteamos con getegid() y geteuid();, que devuelven el Group ID y el User ID del usuario que está ejecutando el proceso ( el que nos interesa, que es flag01)
Explicandolo un poco, todo proceso en los sistemas Unix tienen al menos dos UID ( User id number ), que suelen ser los mismos:
- real UID number ( identifica al usuario que lanza el proceso )
- effective UID number ( determina que recursos accede el proceso, cuando un proceso abre un fichero,el propietario se determina con el effective UID )
- Y un tercer UID, el saved UID number, que es un tipo de effective UID.
Ahora sólo nos queda setear con setresgid() y setresuid() con el siguiente formato setresuid(ruid,euid,suid) y ejecutar entonces la llamada al sistema.
Empieza el truco cuando se ejecuta la llamada al sistema /usr/bin/env, que nos devuelve la totalidad de las variables de entorno que tenemos configuradas para nuestro usuario, entonces el proceso, a través de env busca en el PATH, que es el siguiente
$ env|grep PATH
$ PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Lo siguiente que hay que conocer es que cuando agregas un directorio al PATH, se agrega y ejecuta de izquierda a derecha, de manera que si creamos un ejecutable que se llame echo ( que es lo que invoca el source code ) en un directorio en el que tengamos permiso de escritura para todos ( /dev/shm a.k.a /tmp ) y agregamos ese directorio al PATH, quedará de la siguiente manera:
$ PATH=/dev/shm:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
Creamos un ejecutable, le llamamos echo, ejecuta una shell via /bin/sh lo guardamos en /dev/shm, and here we go, privilege escalation via command execution !

