Ofuscar código PL/SQL
03/10/2014 -
En ocasiones deseamos que nuestro código PL/SQL no sea fácilmente accesible a los usuarios y/o administradores de las BBDD en las que lo tenemos instalado, sea para evitar copias o modificaciones no autorizadas. En parte estos objetivos los podemos conseguir “ofuscando” nuestro código. Notar que el objetivo no es “cifrar” el código, ya que existen maneras de llegar a revertir el proceso, mas bien se trata de no permitir un acceso libre a él. Es posible conseguirlo utilizando la utilidad de línea de comando PL/SQL Wrapper o el procedimiento de base de datos DBMS_DDL.WRAP.
El objetivo de este post va a ser mostrar cómo ofuscar el código PL/SQL de nuestras aplicaciones mediante la utilidad de línea de comando PL/SQL Wrapper.
- La documentación para la versión 11gR2 en el momento de creación de este post se puede consultar en este link.
- Se puede ofuscar el código de paquetes (tanto especificación, como cuerpo, como ambos), tipos (tanto especificación, como cuerpo, como ambos), funciones y procedimientos. No se puede ofuscar triggers, aunque desde el trigger sí se puede referenciar a un procedimiento ofuscado.
- El código ofuscado se puede compilar, exportar e importar como el código “en claro”, pero hay que tener cuidado con las versiones de base de datos, ya que no existe compatibilidad hacia atrás, es decir, el código compilado en una versión 11g no funcionará en una 10g, el de la 10g no funcionará en una 9i y así.
- Oracle no proporciona mecanismos ni herramientas para revertir esa ofuscación una vez se ha ofuscado el código, y, aunque existen formas de conseguirlo, no es el alcance de este post. Si se desea modificar el código es necesario editar el fichero original, volverlo a ofuscar y cargarlo en la base de datos.
La utilidad de línea de comando consiste en el ejecutable ‘wrap’. La sintaxis del comando es la siguiente:
1
|
wrap iname=input_file [ oname=output_file ] |
Si no se le indica fichero de salida creará por defecto uno con el mismo nombre que el de entrada pero con extensión .plb
Vamos a mostrar un ejemplo de ofuscación de un procedimiento. Suponiendo que el código fuente del procedimiento P_PRUEBA, guardado en el fichero ‘p_prueba.sql’, sea el siguiente:
1
2
3
4
5
6
|
create or replace PROCEDURE P_PRUEBA AS v_fecha VARCHAR2(30); BEGIN select sysdate into v_fecha from dual; dbms_output.put_line(v_fecha); END P_PRUEBA; |
Ejecutando el comando wrap sin indicarle fichero de salida crea por defecto un fichero con el mismo nombre que el de entrada pero con extensión plb:
1
2
3
4
5
6
7
|
C:\ TEMP >wrap iname=p_prueba.sql PL/SQL Wrapper: Release 11.2.0.3.0- 64bit Production on Wed Oct 01 10:36:45 2014 Copyright (c) 1993, 2009, Oracle. All rights reserved. Processing p_prueba.sql to p_prueba.plb |
El contenido del fichero plb es el siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
create or replace PROCEDURE P_PRUEBA wrapped a000000 369 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 7 8d ba Y0aSZVIhKd/E6nP/BvoxZ9iMOBMwgwDw2stqfHSE2sGOq+tjFoOzt37VO/vG39K9UPr+nekh jojny88UW/6iMXVwR69g8/tEb6kLSIm851vC/Z08/k4cp1pPJXqU5YmOXUmIjQ4hzeoLhryE 39ivr3a/WFX1dSJxA6dgHk/SACc6e8vEtp6tFPY= / |
A continuación, previamente conectados a la base de datos, comprobamos el código fuente del paquete y lo ejecutamos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
SQL> select name ,type,line,text from user_source where name = 'P_PRUEBA' ; NAME TYPE LINE TEXT ---------- ---------- ---- ------------------------------------------------------------ P_PRUEBA PROCEDURE 1 PROCEDURE P_PRUEBA AS P_PRUEBA PROCEDURE 2 v_fecha VARCHAR2(30); P_PRUEBA PROCEDURE 3 BEGIN P_PRUEBA PROCEDURE 4 select sysdate into v_fecha from dual; P_PRUEBA PROCEDURE 5 dbms_output.put_line(v_fecha); P_PRUEBA PROCEDURE 6 END P_PRUEBA; 6 rows selected. SQL> set serveroutput on SQL> alter session set nls_date_format= 'dd/mm/yy hh24:mi:ss' ; Session altered. SQL> exec p_prueba; 28/09/14 21:40:36 PL/SQL procedure successfully completed. |
Recreamos el procedimiento con el código ofuscado, para, a continuación, comprobar el código y la ejecución:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
SQL> @C:\ TEMP \p_prueba.plb Procedure created. SQL> select name ,type,line,text from user_source where name = 'P_PRUEBA' ; NAME TYPE LINE TEXT ---------- ---------- ---- ------------------------------------------------------------ P_PRUEBA PROCEDURE 1 PROCEDURE P_PRUEBA wrapped a000000 369 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 7 8d ba Y0aSZVIhKd/E6nP/BvoxZ9iMOBMwgwDw2stqfHSE2sGOq+tjFoOzt37VO/vG 39K9UPr+nekh jojny88UW/6iMXVwR69g8/tEb6kLSIm851vC/Z08/k4cp1pPJXqU5YmOXUmI jQ4hzeoLhryE 39ivr3a/WFX1dSJxA6dgHk/SACc6e8vEtp6tFPY= SQL> exec p_prueba; 28/09/14 21:43:29 PL/SQL procedure successfully completed. |
Como hemos visto, el procedimiento P_PRUEBA funciona igual ofuscado que sin ofuscar, no afecta a su uso, por tanto ofuscar código tiene un impacto nulo en las aplicaciones y, de esta manera, es posible evitar que se acceda a él.