Skip to content

Instantly share code, notes, and snippets.

@benbasson
Last active July 15, 2020 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save benbasson/dfbb94e2e0615c87fdff to your computer and use it in GitHub Desktop.
Save benbasson/dfbb94e2e0615c87fdff to your computer and use it in GitHub Desktop.
Oracle default password checker script
DECLARE
TYPE t_table_of_vc30 IS TABLE OF VARCHAR2(30);
-- A bunch of obvious / default passwords, most of which are taken from
-- Pete Finnigan's list:
-- <http://www.petefinnigan.com/default/default_password_list.htm>
l_base_weak_passwords t_table_of_vc30 := t_table_of_vc30(
'dev'
, 'dev1'
, 'st'
, 'st1'
, 'uat'
, 'uat1'
, '6071992'
, '199220706'
, '0racl3'
, '0racl38'
, '0racl38i'
, '0racl39'
, '0racl39i'
, '0racle'
, '0racle8'
, '0racle8i'
, '0racle9'
, '0racle9i'
, 'abm'
, 'adgangskode'
, 'adldemo'
, 'admin'
, 'administrator'
, 'ahl'
, 'ahm'
, 'airoplane'
, 'ak'
, 'akf7d98s2'
, 'alr'
, 'ams'
, 'amv'
, 'anonymous'
, 'ap'
, 'applmgr'
, 'applsys'
, 'applsyspub'
, 'apppassword'
, 'apps'
, 'aq'
, 'aqdemo'
, 'aqjava'
, 'aquser'
, 'ar'
, 'asf'
, 'asg'
, 'asl'
, 'aso'
, 'asp'
, 'ast'
, 'audiouser'
, 'ax'
, 'az'
, 'bar'
, 'bc4j'
, 'ben'
, 'bic'
, 'bil'
, 'bim'
, 'bis'
, 'biv'
, 'bix'
, 'blewis'
, 'bom'
, 'brio_admin'
, 'bsc'
, 'bug_reports'
, 'catalog'
, 'cct'
, 'cdemo82'
, 'cdemo83'
, 'cdemocor'
, 'cdemorid'
, 'cdemoucb'
, 'cdouglas'
, 'ce'
, 'centra'
, 'central'
, 'change_on_install'
, 'cids'
, 'cis'
, 'cisinfo'
, 'clave'
, 'clerk'
, 'cloth'
, 'cn'
, 'company'
, 'compiere'
, 'crp'
, 'cs'
, 'csc'
, 'csd'
, 'cse'
, 'csf'
, 'csi'
, 'csl'
, 'csmig'
, 'csp'
, 'csr'
, 'css'
, 'ctxdemo'
, 'ctxsys'
, 'cua'
, 'cue'
, 'cuf'
, 'cug'
, 'cui'
, 'cun'
, 'cup'
, 'cus'
, 'cz'
, 'd_syspw'
, 'd_systpw'
, 'dbsnmp'
, 'dbvision'
, 'demo'
, 'demo8'
, 'demo9'
, 'des'
, 'des2k'
, 'dev2000_demos'
, 'dip'
, 'discoverer_admin'
, 'dmsys'
, 'dpfpass'
, 'dsgateway'
, 'dssys'
, 'dtsp'
, 'eaa'
, 'eam'
, 'east'
, 'ec'
, 'ecx'
, 'ejb'
, 'ejsadmin'
, 'ejsadmin_password'
, 'emp'
, 'eng'
, 'eni'
, 'estore'
, 'event'
, 'evm'
, 'example'
, 'exfsys'
, 'extdemo'
, 'extdemo2'
, 'fa'
, 'fem'
, 'fii'
, 'finance'
, 'finprod'
, 'flm'
, 'fnd'
, 'fndpub'
, 'fpt'
, 'frm'
, 'fte'
, 'fv'
, 'gl'
, 'gma'
, 'gmd'
, 'gme'
, 'gmf'
, 'gmi'
, 'gml'
, 'gmp'
, 'gms'
, 'gpfd'
, 'gpld'
, 'gr'
, 'hades'
, 'hcpark'
, 'hlw'
, 'hobbes'
, 'hr'
, 'hri'
, 'hvst'
, 'hxc'
, 'hxt'
, 'iba'
, 'ibe'
, 'ibp'
, 'ibu'
, 'iby'
, 'icdbown'
, 'icx'
, 'idemo_user'
, 'ieb'
, 'iec'
, 'iem'
, 'ieo'
, 'ies'
, 'ieu'
, 'iex'
, 'ifssys'
, 'igc'
, 'igf'
, 'igi'
, 'igs'
, 'igw'
, 'imageuser'
, 'imc'
, 'imedia'
, 'imt'
, 'instance'
, 'inv'
, 'invalid'
, 'ipa'
, 'ipd'
, 'iplanet'
, 'isc'
, 'itg'
, 'ja'
, 'je'
, 'jetspeed'
, 'jg'
, 'jl '
, 'jmuser'
, 'john'
, 'jtf'
, 'jtm'
, 'jts'
, 'kwalker'
, 'l2ldemo'
, 'laskjdf098ksdaf09'
, 'lbacsys'
, 'manag3r'
, 'manager'
, 'manprod'
, 'mddata'
, 'mddemo'
, 'mddemo_mgr'
, 'mdsys'
, 'me'
, 'mfg'
, 'mgr'
, 'mgwuser'
, 'migrate'
, 'miller'
, 'mmo2'
, 'mmo3'
, 'moreau'
, 'mot_de_passe'
, 'mrp'
, 'msc'
, 'msd'
, 'mso'
, 'msr'
, 'mt6ch5'
, 'mtrpw'
, 'mts_password'
, 'mtssys'
, 'mumblefratz'
, 'mwa'
, 'mxagent'
, 'names'
, 'neotix_sys'
, 'nneulpass'
, 'oas_public'
, 'ocitest'
, 'ocm_db_admin'
, 'odm'
, 'ods'
, 'ods_server'
, 'odscommon'
, 'oe'
, 'oem_temp'
, 'oemadm'
, 'oemrep'
, 'okb'
, 'okc'
, 'oke'
, 'oki'
, 'oko'
, 'okr'
, 'oks'
, 'okx'
, 'olapdba'
, 'olapsvr'
, 'olapsys'
, 'ont'
, 'oo'
, 'openspirit'
, 'opi'
, 'oracache'
, 'oracl3'
, 'oracle'
, 'oracle8'
, 'oracle8i'
, 'oracle9'
, 'oracle9i'
, 'oradbapass'
, 'oraprobe'
, 'oraregsys'
, 'orasso'
, 'orasso_ds'
, 'orasso_pa'
, 'orasso_ps'
, 'orasso_public'
, 'orastat'
, 'ordcommon'
, 'ordplugins'
, 'ordsys'
, 'osm'
, 'osp22'
, 'ota'
, 'outln'
, 'owa'
, 'owa_public'
, 'owf_mgr'
, 'owner'
, 'ozf'
, 'ozp'
, 'ozs'
, 'pa'
, 'panama'
, 'paper'
, 'parol'
, 'passwd'
, 'passwo1'
, 'passwo2'
, 'passwo3'
, 'passwo4'
, 'password'
, 'patrol'
, 'paul'
, 'perfstat'
, 'perstat'
, 'pjm'
, 'planning'
, 'plex'
, 'pm'
, 'pmi'
, 'pn'
, 'po'
, 'po7'
, 'po8'
, 'poa'
, 'pom'
, 'portal_demo'
, 'portal_sso_ps'
, 'portal30'
, 'portal30_admin'
, 'portal30_demo'
, 'portal30_ps'
, 'portal30_public'
, 'portal30_sso'
, 'portal30_sso_admin'
, 'portal30_sso_ps'
, 'portal30_sso_public'
, 'portal31'
, 'pos'
, 'powercartuser'
, 'primary'
, 'psa'
, 'psb'
, 'psp'
, 'pub'
, 'pubsub'
, 'pubsub1'
, 'pv'
, 'qa'
, 'qdba'
, 'qp'
, 'qs'
, 'qs_adm'
, 'qs_cb'
, 'qs_cbadm'
, 'qs_cs'
, 'qs_es'
, 'qs_os'
, 'qs_ws'
, 're'
, 'rep_owner'
, 'repadmin'
, 'reports'
, 'rg'
, 'rhx'
, 'rla'
, 'rlm'
, 'rmail'
, 'rman'
, 'rrs'
, 'sample'
, 'sampleatm'
, 'sap'
, 'sapr3'
, 'sdos_icsap'
, 'secdemo'
, 'senha'
, 'serviceconsumer1'
, 'sh'
, 'shelves'
, 'si_informtn_schema'
, 'siteminder'
, 'slidepw'
, 'snowman'
, 'spierson'
, 'ssp'
, 'starter'
, 'steel'
, 'strat_passwd'
, 'supersecret'
, 'support'
, 'swordfish'
, 'swpro'
, 'swuser'
, 'sympa'
, 'sys'
, 'sys_stnt'
, 'sysadm'
, 'sysadmin'
, 'sysman'
, 'syspass'
, 'system'
, 'systempass'
, 'tahiti'
, 'tdos_icsap'
, 'tectec'
, 'test'
, 'test_user'
, 'testpilot'
, 'thinsamplepw'
, 'tibco'
, 'tiger'
, 'tigger'
, 'tip37'
, 'trace'
, 'travel'
, 'tsdev'
, 'tsuser'
, 'turbine'
, 'ultimate'
, 'um_admin'
, 'um_client'
, 'unknown'
, 'user'
, 'user0'
, 'user1'
, 'user2'
, 'user3'
, 'user4'
, 'user5'
, 'user6'
, 'user7'
, 'user8'
, 'user9'
, 'utility'
, 'utlestat'
, 'vea'
, 'veh'
, 'vertex_login'
, 'videouser'
, 'vif_dev_pwd'
, 'viruser'
, 'vrr1'
, 'vrr2'
, 'webcal01'
, 'webdb'
, 'webread'
, 'welcome'
, 'west'
, 'wfadmin'
, 'wh'
, 'wip'
, 'wk_test'
, 'wkadmin'
, 'wkproxy'
, 'wksys'
, 'wkuser'
, 'wms'
, 'wmsys'
, 'wob'
, 'wood'
, 'wps'
, 'wsh'
, 'wsm'
, 'www'
, 'wwwuser'
, 'xademo'
, 'xdp'
, 'xla'
, 'xnc'
, 'xni'
, 'xnm'
, 'xnp'
, 'xns'
, 'xprt'
, 'xtr'
, 'xxx'
, 'yes'
, 'your_pass'
, 'zwerg'
);
l_username_passwords t_table_of_vc30;
l_test_10g_passwords t_table_of_vc30;
l_test_11g_passwords t_table_of_vc30;
l_temp t_table_of_vc30 := t_table_of_vc30();
l_counter_for_summary PLS_INTEGER := 0;
l_10g_pwd_count PLS_INTEGER;
l_not_upgraded_pwd_count PLS_INTEGER;
-- SHA1 hashes the password mimicking the Oracle 11g implementation
FUNCTION password_hash (
p_password VARCHAR2
, p_salt VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
RETURN dbms_crypto.hash(
src => utl_raw.cast_to_raw(p_password)||hextoraw(p_salt)
, typ => dbms_crypto.HASH_SH1
);
END password_hash;
-- Builds up the spare4 column syntax (as per 11g password storage model)
FUNCTION generate_spare4 (
p_password VARCHAR2
, p_salt VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
RETURN 'S:' || password_hash(p_password, p_salt) || p_salt;
END generate_spare4;
-- Builds up an Oracle 10g (and prior) password hash
-- Derived from Pete Finnigan's password cracking routines:
-- <http://www.petefinnigan.com/oracle_password_cracker.htm>
FUNCTION generate_10g_password (
p_username VARCHAR2
, p_password VARCHAR2
)
RETURN VARCHAR2
IS
DES_KEY CONSTANT RAW(128) := HEXTORAW('0123456789ABCDEF');
l_username_password VARCHAR2(70);
l_username_password_length PLS_INTEGER;
l_encoded_string VARCHAR2(124);
l_length_modulus PLS_INTEGER;
l_username_password_raw RAW(2048);
l_des_first_pass_raw RAW(2048);
l_key2 RAW(128);
l_password_hash_raw RAW(2048);
l_hex_str VARCHAR2(2048);
l_hex_str_length PLS_INTEGER;
l_10g_password_hash VARCHAR2(16);
BEGIN
l_username_password := UPPER(p_username) || UPPER(p_password);
l_username_password_length := LENGTH(l_username_password);
-- Pad each character in the string with a zero byte sequence
FOR i IN 1 .. l_username_password_length LOOP
l_encoded_string := l_encoded_string || CHR(0) || SUBSTR(l_username_password, i, 1);
END LOOP;
-- Pad the whole string so it aligns to an 8 byte boundary
l_length_modulus := MOD(LENGTH(l_encoded_string), 8);
IF l_length_modulus > 0 THEN
l_encoded_string := RPAD(l_encoded_string, LENGTH(l_encoded_string) + 8 - l_length_modulus, CHR(0));
END IF;
-- Cast the encoded string as a RAW for DES
l_username_password_raw := utl_raw.cast_to_raw(l_encoded_string);
-- First pass DES
l_des_first_pass_raw := dbms_obfuscation_toolkit.DESEncrypt(
input => l_username_password_raw
, key => DES_KEY
);
l_hex_str := RAWTOHEX(l_des_first_pass_raw);
l_hex_str_length := LENGTH(l_hex_str);
l_key2 := HEXTORAW(SUBSTR(l_hex_str, (l_hex_str_length - 16 + 1), 16));
-- Second pass DES
l_password_hash_raw := dbms_obfuscation_toolkit.DESEncrypt(
input => l_username_password_raw
, key => l_key2
);
l_hex_str := HEXTORAW(l_password_hash_raw);
l_hex_str_length := LENGTH(l_hex_str);
l_10g_password_hash := SUBSTR(l_hex_str,(l_hex_str_length - 16 + 1),16);
RETURN l_10g_password_hash;
END generate_10g_password;
BEGIN
-- Check for instances where password is a username (not necessarily the same user)
SELECT username
BULK COLLECT INTO l_username_passwords
FROM dba_users;
-- 10g passwords are case insensitive, so just add the usernames to the set (they'll all get UPPER'd anyway)
l_test_10g_passwords := l_base_weak_passwords MULTISET UNION DISTINCT l_username_passwords;
-- Now lower, upper, initcap each password for some crude variations for 11g password storage checks (case sensitive)
FOR idx IN l_test_10g_passwords.FIRST .. l_test_10g_passwords.LAST LOOP
l_temp.EXTEND(3);
l_temp(l_temp.COUNT - 2) := LOWER(l_test_10g_passwords(idx));
l_temp(l_temp.COUNT - 1) := UPPER(l_test_10g_passwords(idx));
l_temp(l_temp.COUNT) := INITCAP(l_test_10g_passwords(idx));
END LOOP;
l_test_11g_passwords := l_test_10g_passwords MULTISET UNION DISTINCT l_temp;
<<user_loop>>
FOR r_user IN (
SELECT
usr.name
, usr.password
, usr.spare4
, SUBSTR(usr.spare4,-20) salt
FROM sys.user$ usr
WHERE EXISTS (
SELECT 1
FROM dba_users dusr
WHERE dusr.username = usr.name
AND dusr.account_status = 'OPEN'
)
ORDER BY usr.name
)
LOOP
-- Only check the 10g hash if an 11g hash isn't stored, no need to check both
IF r_user.spare4 IS NULL AND r_user.password IS NOT NULL THEN
<<test_10g_password_loop>>
FOR idx IN l_test_10g_passwords.FIRST .. l_test_10g_passwords.LAST LOOP
IF r_user.password = generate_10g_password(r_user.name, l_test_10g_passwords(idx)) THEN
dbms_output.put_line('User ' || r_user.name || ' has a predictable password (NB: stored in less secure 10g format)');
l_counter_for_summary := l_counter_for_summary + 1;
CONTINUE user_loop;
END IF;
END LOOP;
END IF;
-- Always check the 11g hashes if they are present
IF r_user.spare4 IS NOT NULL THEN
<<test_11g_password_loop>>
FOR idx IN l_test_11g_passwords.FIRST .. l_test_11g_passwords.LAST LOOP
IF r_user.spare4 = generate_spare4(l_test_11g_passwords(idx), r_user.salt) THEN
dbms_output.put_line('User ' || r_user.name || ' has a predictable password');
l_counter_for_summary := l_counter_for_summary + 1;
CONTINUE user_loop;
END IF;
END LOOP;
END IF;
END LOOP user_loop;
SELECT
COUNT(*)
, SUM(CASE WHEN usr.spare4 IS NULL THEN 1 ELSE 0 END)
INTO
l_10g_pwd_count
, l_not_upgraded_pwd_count
FROM sys.user$ usr
WHERE EXISTS (
SELECT 1
FROM dba_users dusr
WHERE dusr.username = usr.name
AND dusr.account_status = 'OPEN'
)
AND usr.password IS NOT NULL;
IF l_counter_for_summary = 0 THEN
dbms_output.put_line('** No unlocked users found with weak passwords');
ELSIF l_counter_for_summary > 0 THEN
dbms_output.put_line('** Number of users with weak passwords: ' || l_counter_for_summary);
END IF;
IF l_10g_pwd_count > 0 THEN
dbms_output.put_line('** Number of users with password stored in 10g format: ' || l_10g_pwd_count);
dbms_output.put_line('** Number of users with password stored *only* in 10g format: ' || l_not_upgraded_pwd_count);
dbms_output.put_line('** If you do not require 10g compatibility, you should NULL out the old hashes from sys.user$ ("password" column) to increase security.');
END IF;
END;
/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment