Voici un petit truc pour rechercher des mots de passe (en texte clair) de BD Oracle en mémoire de processus Java. Les programmes utilisés proviennent du JDK standard d'Oracle.
Lister les programmes java en utilisant
jps:
$ jps
32488 MainClassName
1945 Jps
La commande
jps permet d'avoir la liste des processus java "instrumentés". L'autre approche (plus inclusive) serait d'utiliser quelque chose comme
pgrep java.
Lorsqu'on a le PID, on peut utiliser
jmap pour générer une image de la mémoire:
$ jmap -heap:format=b 32488
Attaching to process ID 32488, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.66-b17
Dumping heap to heap.bin ...
Heap dump file created
Une fois l'image créée, on peut l'analyser en utilisant
jhat. Cette commande démarre un serveur web qui permet l'analyse.
[t903335@slave1 ~]$ jhat heap.bin
Reading from heap.bin...
Dump file created Tue Apr 19 23:11:01 UTC 2016
Snapshot read, resolving...
Resolving 386035 objects...
[...]
WARNING: Failed to resolve object id 0x585dc0618 for field clazz (signature L)
Chasing references, expect 77 dots.............................................................................
Eliminating duplicate references.............................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
En connectant sur le port mentionné ci-haut avec un navigateur web (http://127.0.0.1:7000/), on obtient la liste de classes java trouvées en mémoire. Au bas de la page, il y a un lien intitulé
Execute Object Query Language (OQL) query qui nous envoie à /oql. Cette page permet d'exécuter des recherches ciblées de la mémoire.
En faisant un peu de recherche, j'ai remarqué que pour trouver le mot de passe qui est envoyé à la BD, il suffit d'exécuter cette recherche OQL:
OQL Query: heap.findClass("oracle.jdbc.driver.T4CConnection")
Si ce pilote JDBC est utilisé par le programme java, on obtiendra un lien vers cette classe. En cliquant sur ce lien, on a l'option de visionner ses instances en cliquant sur le lien
Instances: Exclude subclasses. Dans la page suivante on verra quelque chose comme:
oracle.jdbc.driver.T4CConnection@0x5861d36a8 (1362 bytes)
Total of 1 instances occupying 1362 bytes.
En cliquant sur le lien vers l'instance, on aura une page suivante qui montrera les différentes valeurs des différents attributs de l'objet en question. Parmi un de ces attributs se trouve
password,
userName et
database (URI). Bien sûr, toutes les valeurs sont les valeurs originales (dans le clair)!
Il me reste à rechercher comment on peut éviter cette exposition continue en mémoire du mot de passe à même le pilote JDBC de Oracle. J'espère que ce n'est qu'une erreur d'implantation (par le développeur-utilisateur du pilote).
Référence OQL:
https://visualvm.java.net/oqlhelp.html
__________________________
Below is a trick for finding clear text password in Java VM memory when a java program utilizes (one of) the JDBC driver(s) from Oracle (ojdbc6.jar I think). The commands used come from the standard Oracle JDK..
To list java programs, use
jps:
$ jps
32488 MainClassName
1945 Jps
The
jps command lists the instrumented java processes. Another approach to get a more incluse list would be to use something like
pgrep java.
Once we have the PID, we can use
jmap to dump the java process memory to disk:
$ jmap -heap:format=b 32488
Attaching to process ID 32488, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.66-b17
Dumping heap to heap.bin ...
Heap dump file created
Once we have the memory dump, we can analyze it using
jhat. This command also starts a web server for the analyst.
$ jhat heap.bin
Reading from heap.bin...
Dump file created Tue Apr 19 23:11:01 UTC 2016
Snapshot read, resolving...
Resolving 386035 objects...
[...]
WARNING: Failed to resolve object id 0x585dc0618 for field clazz (signature L)
Chasing references, expect 77 dots.............................................................................
Eliminating duplicate references.............................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
When connecting to that port with a web browser
(http://127.0.0.1:7000/), we obain a list of java classes found in memory. At the bottom of the page, there's a link
Execute Object Query Language (OQL) query that brings us to /oql. This page allows searching for structured memory content.
After a bit of tinkering, I figured out that to find the database password, all I needed to do is to run this OQL query:
OQL Query: heap.findClass("oracle.jdbc.driver.T4CConnection")
If this JDBC driver is used in the java program, we obtain a link to this class. When clicking that link, we can view its instance(s) by clicking on
Instances: Exclude subclasses. In the following page, we get something like:
oracle.jdbc.driver.T4CConnection@0x5861d36a8 (1362 bytes)
Total of 1 instances occupying 1362 bytes.
When clicking on the link for the instance, we get another page with different attributes and corresponding values within the object. As part of these, we find the attributes named
password,
userName and
database (URI). Of course, all of those values are in the clear!
Now, I need to find a way to avoid this continuous exposure in memory when using Oracle drivers. There's hopefully a better way to use it or simply a better driver altogether...
More details on OQL:
https://visualvm.java.net/oqlhelp.html