Oracle listener password encryption
Oracle clients were able to remotely administer the Listener service with the lsnrctl utility. These administrative functions in Oracle versions before 10.1 were enabled by default and a password was used to authenticate clients connecting to the service. In the 10.1 and later versions of Oracle, the administrative functions are disabled by default so the listener password is usually not set.This article gives an overview of the hashing function used to store Oracle listener passwords in version 10g and 11g. The algorithm is described in a detailed level and a sample implementation is provided (written in Python using pyDES [3]). Special thanks to Gergely Toth and Laszlo Toth, who reviewed this article.
The Oracle listener stores the listener password in a file named 搇istener.ora [2]. The password is hashed with a one way function described below. Result of the function is a number consisting of eight bytes. This number is converted to a 16 character long string containing the hexadecimal digits in a human readable form.
The algorithm used to calculate the listener password hashes is not openly documented for Oracle version 10g and 11g (see [4] for the listener hash in Oracle version 9i). The steps are similar to the Oracle Password Hashing Algorithm published in [1], however there are differences in converting the password before feeding it to the DES CBC encryption.
We call the function which converts the password into to 8-byte-long data blocks for DES encryption as 揑nitial Permutation later in this article. Then the order of bytes in every four byte blocks is reversed (i.e. 0x0102030405060708 is converted to 0x0403020108070605) before given to the encryption function.
The pseudo code for the 揑nitial Permutation function:
1. Concatenate the string "Arb" and the password to produce a plaintext string;
2. Convert the plaintext string to uppercase characters;
3. Expand the plaintext string with zero bytes so that the length is a multiple of 4;
4. Swap the order of every byte pair;
5. Convert the bytes generated in previous steps to multi-byte storage format: all characters and zero bytes have the high byte set to 0x00; now the length is the multiple of 8.
The hashing method:
1. Use the 揑nitial Permutation function to convert the password into an eight-byte-long data blocks for DES;
2. Reverse the order of bytes in every four byte blocks as mentioned above;
3. Encrypt the plaintext string using the DES algorithm in cipher block chaining (CBC) mode with a fixed key value of 0x0123456789ABCDEF;
4. Encrypt the plaintext string again with DES-CBC using the last block of the result of step 4 as the encryption key;
5. The last block from the output of step 4 is converted into a printable hexadecimal string.
An example for password "1234567890":
Step
|
String
|
Hexadecimal
|
1. | Arb1234567890 | 41 72 62 31 32 33 34 35 36 37 38 39 30 |
2. | ARB1234567890 | 41 52 42 31 32 33 34 35 36 37 38 39 30 |
3. | ARB1234567890... | 41 52 42 31 32 33 34 35 36 37 38 39 30 00 00 00 |
4. | RA1B32547698.0.. | 52 41 31 42 33 32 35 34 37 36 39 38 00 30 00 00 |
5. | R.A.1.B.3.2.5.4. 7.6.9.8...0..... | 52 00 41 00 31 00 42 00 33 00 32 00 35 00 34 00 37 00 36 00 39 00 38 00 00 00 30 00 00 00 00 00 |
REFERENCES
[1] An Assessment of the Oracle Password Hashing Algorithm (2005)
Authors: Joshua Wright, Carlos Cid
http://www.isg.rhul.ac.uk/~ccid/publications/oracle_passwd.pdf
[2] Oracle Database Listener Security Guide - Integrigy White Paper (2007)
Authors: Stephen Kost and Jack Kanter
http://www.integrigy.com/security-resources/whitepapers/Integrigy_Oracle_Listener_TNS_Security.pdf
[3] A pure python module which implements the DES and Triple-DES encryption algorithms.
http://sourceforge.net/projects/pydes/
[4] Topic: Key and algo for encrypting the listener password
http://www.petefinnigan.com/forum/yabb/YaBB.cgi?board=ora_sec;action=display;num=1185585279
SOURCE CODE
Python implementation (using the pyDes module)
The first command line argument is the password to hash.