Reverse engineering DB Link password decryption in PL/SQL

This is my third blog post about DB Link encryption/decryption.In the first one i demonstrated how we can find the database link password in clear text using GDB and Intel pin tools.In the second one i have given more information about how it was encrypted/decrypted (AES in CBC encryption mode).It’s now time to reverse engineer it !

NOTE : All the test are done in oracle 12.1.0.2.6/OEL6/UEK4

Update 08/03/2017 : The script also work in oracle 12.2.0.1

As explained in my previous post to decrypt the password we need three things.

  • Initialization vector
  • Ciphertext
  • Encryption Key

After some investigation it appeared that this parameters are not depending only on “PASSWORDX” of “sys.link$” but also in two other parameters :

  • NO_USERID_VERIFIER_SALT in table sys.props$ (Database dependent).

SELECT VALUE$
FROM SYS.PROPS$
WHERE name = 'NO_USERID_VERIFIER_SALT';

  • Variable “ztcshpl_v6” fixed across different databases(note:same value in 11.2.0.4 was named ztcshpl_v6.0)

readelf -s oracle |  grep ztcshpl_v6
112105: 0000000010b9ee40 16384 OBJECT  LOCAL  DEFAULT   29 ztcshpl_v6

Here is some info about how this different parameters combine :

  • Initialization vector : Using the second byte of passwordx to lookup in ztcshpl_v6
  • Ciphertext : Using ztcshpl_v6 and passwordx
  • Encryption Key : Calculated as a XOR between two keys :
    • Key 1 : Using ztcshpl_v6 and passwordx
    • Key 2 : Hash sha256 of NO_USERID_VERIFIER_SALT

Installation : (This script use Connor McDonald Package “bitops2” for bit operation like “XOR” bitops2.bitxor )

Update 08/03/2017 : the script bitops2.sql is not needed any more just install db_link_password_decrypt.sql

Time for a DEMO :

The procedure “db_link_password_decrypt” take two parameters :

  • NO_USERID_VERIFIER_SALT of your database
  • passwordx from sys.link$

Let’s create two database link and test it !


CREATE DATABASE LINK HATEM_TEST1
CONNECT TO HATEM
IDENTIFIED BY "you_can_not_hide_from_me"
USING 'testdb';

CREATE DATABASE LINK HATEM_TEST2
CONNECT TO HATEM
IDENTIFIED BY "oups%you$found_me"
USING 'testdb';

Password decryption :

First Database Link :


exec db_link_password_decrypt('17B21F905CE739E2759E6FB99745650E','076C8B8463098676
E408141A154CF4C20AAF19A52CF7FEF3CD8A99830A82F9D8F129665C2F395DF4F30EBE1
5E48D78096E9BD8AC1012D24525982CE3C828BE298EA798D6FBD8A18379DEE803692B
773B86570AB2DA90EA121124D6D0F228818D18812B42C77AE6D0F4BF257627643EEC34F
B9A6C2EF6185D7302EF30673A2F4C');

capture-01

Second Database Link :

exec db_link_password_decrypt('17B21F905CE739E2759E6FB99745650E','072D8692F86F55A14
96141309CBEED0DFF2F03D90B3EBF1E3AE7518DAF66B768DC171779ECB7A8546C19AD83A1CF0878667D
22EC9550AD8785E8A3A48016883C8CA085E87A6121462825FEF94866EC8869E04F0E5D73FAB39A005A
09EA98945B43C06F48B2DD8E1D6943AA693C36E945B005464EF13C257F6D085530C5D038AC');

capture-02

UPDATE  25/05/2018 : The script can now be run from sqlplus and the noise from the recovered value has been eliminated. Thanks Adric Norris for you contribution.

Capture test5

That’s it 😀

14 thoughts on “Reverse engineering DB Link password decryption in PL/SQL

    • i have oracle version :

      Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – Production
      PL/SQL Release 11.2.0.3.0 – Production
      CORE 11.2.0.3.0 Production
      TNS for Linux: Version 11.2.0.3.0 – Production
      NLSRTL Version 11.2.0.3.0 – Production

      I Got error when I run db_link_password_decrypt.sql
      “PROCEDURE HRPROD.DB_LINK_PASSWORD_DECRYPT
      On line: 37
      PLS-00302: component ‘HASH_SH256’ must be declared”

      how to solve this ?

      thanks in advance

  1. for someone not very deep into “playing with bytes”
    – how did you come from readelf output to your very long number in plsql ?

    For me in 12.1.0.4 seems not to work and only the in doubt input is ztcshpl_v6″.

  2. Hi basile , I used gdb and the command x to examine the memory address content and as stated i only tested in specific oracle versions/platform so it may need some adjustment for other versions.The idea here is to show what can be done 🙂

  3. Just Amazing! 🙂

    Tested it on a 12.1.0.2 database on windows and it worked!!

    This script cannot be run using SQLPLUS which has a limit of 2000 characters per line.

    I used Oracle SQLCL which doesn’t have that limitation.

  4. i have oracle version :

    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – Production
    PL/SQL Release 11.2.0.3.0 – Production
    CORE 11.2.0.3.0 Production
    TNS for Linux: Version 11.2.0.3.0 – Production
    NLSRTL Version 11.2.0.3.0 – Production

    I Got error when I run db_link_password_decrypt.sql
    “PROCEDURE HRPROD.DB_LINK_PASSWORD_DECRYPT
    On line: 37
    PLS-00302: component ‘HASH_SH256’ must be declared”

    how to solve this ?

    thanks in advance

  5. @hatem-mahmoud

    It turns out that the binary value of the first decrypted byte indicates the plaintext password length, which makes it possible to eliminate the noise from the recovered value. I’ve submitted a PR which adds this tweak.

    • Minor clarification… the length component indicates the number of *bytes* used by the plaintext password, rather than characters. So if the password is set to “€”, for example, the length will indicate 3 (since it’s a 3-byte UTF-8 character) rather than 1.

      This doesn’t make any functional difference to the PR which you merged, as it already handles the scenario correctly, but does mean that my commit message was slightly misleading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s