Archive for the ‘security’ Category

h1

What does the SQL92_SECURITY parameter actually do?

November 23, 2009

Whilst looking at our Grid Control I noticed that we had a few policy violations in the security configuration stating that SQL92_SECURITY=FALSE. These were against some of our older databases as we set it to true on all new builds. I thought I knew what this parameter did but had a look around and determined the following :-

It stops anyone being able to update or delete rows from a table owned by another user if you were using a where clause and did not have select on that table. Fair enough I thought, it sounds like it is some form of ANSI 92 standard and it is all a bit meaningless. I could not see what the issue was but I was intrigued as to why it was an Oracle security recommendation.

I set up the following test case on both a 10G and 11G database where SQL92_SECURITY was set to TRUE. Very simple but I had no failures other than the select statement which had insufficient privileges.

create user usera identified by usera;
create user userb identified by userb;

grant create session,create table to usera;
grant create session to userb;
alter user usera quota unlimited on users;
alter user userb quota unlimited on users;
show parameter sql92_security
connect usera/usera
create table tab1 as select * from all_objects where rownum <101;
select count(*) from tab1;
grant update,delete on tab1 to userb;

connect userb/userb
update usera.tab1 set object_type = 'WAS PACK' where object_type='PACKAGE';
commit;
select distinct status from usera.tab1;
prompt fails as no select privilege on usera.tab1
prompt SQL92 set to true and yet update is allowed ??
prompt now let's try a delete
delete from usera.tab1 where rownum <21;

prompt delete with a where clause works as well

select count(*) from
prompt end of case study

So what is all that about, where was I going wrong and why were my updates and deletes allowed when they shouldn’t have been.

This parameter is meant to prevent you from deleting a table when you specify a condition based on table’s columns. Conditions that are not checking the values stored in the table are allowed(rownum < X, etc.)

In my testcase I deleted the table rows without a condition which read one of the the tables columns. If instead of executing delete from usera.tab1 where rownum =21 I had executed delete from usera.tab1 where object_name = ‘TEST’; I would get an error.

The purpose of this parameter is to allow a user one to delete table data without giving them the possibility of guessing what values are stored in that table. Imagine that there is a table with contacts and I only have delete rights on that table. If I am able to delete the table with a condition based on table columns I can find out via multiple attempts the contents of the table. I can for example find out whether ‘John Smith’ is a contact or not :

SQL> delete from contacts where contact_first_name='John' and contact_family_name='Smith'; 

1 row deleted
SQL> rollback;
Rollback complete.

Since the row was deleted I know now that John Smith is a contact. Then I do a rollback of the transaction and the table is as it was before the delete. If the parameter is set to TRUE I cannot make use of this trick and I can only delete the rows blindly. I will be able to delete without knowing what I am going to delete.

Once I understood what could be done I understood the reason for the init.ora parameter to be enabled. However there is very little information out on the web which explains the reasons and that is why I think the parameter can be misunderstood.

Prior to enabling it on a database that is in use I would check that nobody had update or delete privileges ona table that they did not own where they did not have select privilege.

select *
from dba_tab_privs a
where privilege in ('UPDATE','DELETE')
and not exists (select null
                from   dba_tab_privs b
                where  privilege = 'SELECT'
                and    a.grantor = b.grantor
                and    a.grantee = b.grantee
                and    a.table_name = b.table_name);
h1

Hacking into an Oracle database

September 23, 2008

At a site I was working at they employed a security company to perform penetration testing on a new application (Oracle/Peoplesoft/Unix/Windows/NT). The test was from within the network  and they failed to breach Oracle database security directly. However …

Password guessing against a NT server resulted in the discovery of a domain admin account (db2admin), which resulted in full compromise of this host and also the remaining servers that are members of this domain.

When you build a Windows server you are asked for an initial password (which you are expected to change later on). This password is stored in a build file and as it had not been changed after the installation  it was then used to logon to the domain (any of  the servers as local administrator)This allowed searching of files on the NT server which produced a file containing the oracle account and password to the people account (peoplesoft admin user)

Once onto the database a reasonably privileged account with a weak password was discovered. From there the encrypted values of the users were captured from dba_users and were compared against a known list of passwords and permutations based on the current password i.e. a zero used instead of an ‘o’. This compromised an account with create procedure and from there they were into the OS.

 

These issues have all been resolved and we are much more secure than we were but it just shows how a lapse in security somewhere on the network can allow what appears to be innocuous access which eventually provides full ingress into what is supposed to be a secure system.

h1

More problems with orapwd file and shipping redo logs

May 12, 2008

OEL Linux 11.1.0.6

I had a orapwd file set up on both databases and have restarted the databases since I re-created the orapw file. I could connect using ’sqlplus sys/password@tnsnames_alias as sysdba’ between both nodes and the sys password is the same on both nodes.  However archived redo logs files were not shipping across to the standby node and I was pulling my hair out struggling to get it to work.

Error messages were :-

*** 2008-05-09 09:44:43.898
Redo shipping client performing standby login
OCISessionBegin failed. Error -1
.. Detailed OCI error val is 1031 and errmsg is ‘ORA-01031: insufficient privileges

An attempt to establish secure session using password verifier based approach will be attempted..
OCISessionBegin failed. Error -1
.. Detailed OCI error val is 1031 and errmsg is ‘ORA-01031: insufficient privileges

An attempt to establish secure session using password verifier based approach will be attempted..
OCISessionBegin failed -1
.. Detailed OCI error val is 1017 and errmsg is ‘ORA-01017: invalid username/password; logon denied

*** 2008-05-09 09:44:44.127 1095 krsh.c
Error 1017 received logging on to the standby
————————————————————
Check that the primary and standby are using a password file
and remote_login_passwordfile is set to SHARED or EXCLUSIVE,
and that the SYS password is same in the password files.
returning error ORA-16191
————————————————————


The passwords were lowercase on both nodes. In fact I was using  a cut’n'paste to create both password files, only replacing  the node name.
Eventually I fixed the problem by re-creating the password files on both nodes (for the 3rd or 4th time) and restarting the databases. I added the parameter ignorecase=y and everything sprung to life.

This gets me to think that the password was being translated to uppercase when it came across to the remote node

There is a bug on Metalink (6804839) ORA-01017 (16191) LOGGING ONTO STANDBY WHEN SEC_CASE_SENSITIVE_LOGON=FALSE

The bug detail itself is not public but the title seems to confirm that it that bug is likely to be related to my problem although in my case sec_case_sensitive is set to true on both nodes already.

How annoying metalink can be, searching all sources for ORA-01017 or 16191 (both in the title of that bug) does not bring it up.

Another suggestion was to copy the orapwd file from one server to the other and ensure that permissions are correct

So the short answer is that if you are stuck with a similar problem try recreating the orapwd file with ignorecase=y set