Re: Oracle Application Express / Password hashes

Dhiru Kholia <[email protected]> Thu, 21 Feb 2013 17:53:19 +0530
Newsgroups gmane.comp.security.openwall.john.user,gmane.comp.security.penetration
Message-ID <CANO7a6xiddBQMcw6dkXVrSF9ce6CM0jTT8ezkZxsu1jrYEdOWQ@mail.gmail.com>
On Wed, Feb 20, 2013 at 6:31 PM, Dhiru Kholia <[email protected]> wrote:
> On Wed, Feb 20, 2013 at 5:04 PM, Guillaume Lopes <[email protected]> wrote:
>> I have to crack password hashes from an Oracle application (APEX). The
>> version is APEX 4.0.
>>
>> Do you know a tool or another way to retrieve clear passwords from hashes ?
>
> Please bring this topic to "john-users" mailing list. JtR folks might
> be able to help you.

I was able to figure out the details of APEX 4.2.1 "default" hashing algorithm.

In short, stored hash = hashlib.md5(password + sgid + username).hexdigest()

I am posting a set of scripts to help in dumping APEX hashes from an
Oracle database and then subsequently cracking them using JtR-jumbo.

For step-by-step instructions, please see attached
README-apex-cracking.txt file.

✗ ../run/john -fo:dynamic_1 -t
Benchmarking: dynamic_1: md5($p.$s) (joomla) [128/128 SSE2 intrinsics
10x4x3]... DONE
Many salts:	14166K c/s real, 14166K c/s virtual
Only one salt:	10305K c/s real, 10305K c/s virtual

AFAIK commercial cracking tools (for APEX hashes) don't even come
close to JtR's speed ;)

-- 
Dhiru
apex-hashes.txt (text/plain, 376 B)
ADMIN                                                                                               ,F96D32CBB2FBE17732C3BBAB91C14F3A                                                                                                                                                                                                                               ,               10
apex-hashes-JtR (application/octet-stream, 52 B) - not displayed
dump-apex-hashes.sql (application/octet-stream, 298 B) - not displayed
README-apex-cracking.txt (text/plain, 1.3 KB)
import hashlib

"""

1. Automated Way

C:\apex>sqlplus sys as sysdba

SQL*Plus: Release 11.2.0.2.0 Production on Fri Feb 22 17:20:51 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Enter password:

Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production

SQL> @dump-apex-hashes.sql

$ python apex2john.py apex-hashes.txt > apex-hashes-JtR

$ john pex-hashes-JtR # use JtR-jumbo from https://github.com/magnumripper/JohnTheRipper/
Loaded 1 password hash (dynamic_1: md5($p.$s) (joomla) [128/128 SSE2 intrinsics 10x4x3])
password         (?)
guesses: 1  time: 0:00:00:00 DONE (Thu Feb 21 17:33:43 2013)  c/s: 375  trying: 123456 - boomer

2. Manual Way

SQL> alter session set current_schema = APEX_040200;

Session altered.

SQL> select user_name,web_password2,security_group_id from wwv_flow_fnd_user;

USER_NAME
--------------------------------------------------------------------------------
WEB_PASSWORD2
--------------------------------------------------------------------------------
SECURITY_GROUP_ID
-----------------
ADMIN
F96D32CBB2FBE17732C3BBAB91C14F3A
10

"""

username = "ADMIN"
sgid = "10"
password = "password"

# APEX 4.2.1 algorithm
print hashlib.md5(password + sgid + username).hexdigest()

# should print "f96d32cbb2fbe17732c3bbab91c14f3a" which is the actual hash
apex2john.py (application/octet-stream, 718 B)
#!/usr/bin/env python

import sys

def process_file(filename):
    with open(filename, "r") as f:
        for line in f.readlines():
            data = line.split(',')

            try:
                username, apexhash, sgid = data
            except:
                continue

            username = username.rstrip().lstrip()
            apexhash = apexhash.rstrip().lstrip()
            sgid = sgid.rstrip().lstrip()

            print "$dynamic_1$%s$%s" % (apexhash, sgid + username)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print >>sys.stderr, "Usage: %s <apex-hashes.txt file(s)>" % sys.argv[0]
        sys.exit(-1)

    for i in range(1, len(sys.argv)):
        process_file(sys.argv[i])