TL;DR;
I am getting SELECT
as the audit output instead of the actual (suspected) query SELECT DISTINCT CONVERT(varchar, DecryptByPassphrase(getkey(N'key1'), FIELD1)) as DECRYPTED_FIELD1 FROM view1 WHERE RECORD_ID = $id
. Other queries audit just fine. Why and how do we fix it?
The Suspected Query
SELECT DISTINCT CONVERT(varchar, DecryptByPassphrase(getkey(N'key1'), FIELD1)) as DECRYPTED_FIELD1FROM view1WHERE RECORD_ID = $id;
It may or may not be using prepared statements with a bind variable for the $id
. We have confirmed the connection is via JDBC.
Another query, that audits fine is:
update view1 set FIELD2 = $v1where FIELD3 = $v2;
Actual Audit Records
They are as follows:
event_time | server_principal_name | statement | object_name |
---|---|---|---|
2021-03-02 17:21:03.7901604 | DOMAIN\username | SELECT | view1 |
2021-03-02 17:21:03.7910692 | DOMAIN\username | SELECT | table14 |
2021-03-02 17:21:03.7910692 | DOMAIN\username | SELECT | view4 |
2021-03-02 17:21:03.7920464 | DOMAIN\username | SELECT | table17 |
2021-03-02 17:21:03.7920464 | DOMAIN\username | SELECT | table16 |
2021-03-02 17:21:03.7929764 | DOMAIN\username | SELECT | table15 |
2021-03-02 17:21:03.7929764 | DOMAIN\username | SELECT | view3 |
2021-03-02 17:21:03.7929764 | DOMAIN\username | SELECT | table13 |
2021-03-02 17:21:03.7939486 | DOMAIN\username | SELECT | table12 |
2021-03-02 17:21:03.7939486 | DOMAIN\username | SELECT | table11 |
2021-03-02 17:21:03.7939486 | DOMAIN\username | SELECT | table10 |
2021-03-02 17:21:03.7949390 | DOMAIN\username | SELECT | table9 |
2021-03-02 17:21:03.7949390 | DOMAIN\username | SELECT | view2 |
2021-03-02 17:21:03.7949390 | DOMAIN\username | SELECT | table8 |
2021-03-02 17:21:03.7959682 | DOMAIN\username | SELECT | table8 |
2021-03-02 17:21:03.7959682 | DOMAIN\username | SELECT | table7 |
2021-03-02 17:21:03.7968892 | DOMAIN\username | SELECT | table7 |
2021-03-02 17:21:03.7968892 | DOMAIN\username | SELECT | table6 |
2021-03-02 17:21:03.7978771 | DOMAIN\username | SELECT | otherdb.table5 |
2021-03-02 17:21:03.7978771 | DOMAIN\username | SELECT | table4 |
2021-03-02 17:21:03.7988691 | DOMAIN\username | SELECT | table3 |
2021-03-02 17:21:03.7988691 | DOMAIN\username | SELECT | table2 |
2021-03-02 17:21:03.7988691 | DOMAIN\username | SELECT | table1 |
2021-03-02 17:21:03.8017734 | DOMAIN\username | SELECT @v_key_value = k.key FROM keystable k WHERE k.name = @p_key_name | keystable |
2021-01-15 17:08:00.9462817 | DOMAIN\username | update view1 set FIELD2 = @P0 where FIELD3 = @P1 | ... |
Areas of research
Here are some of the relevant areas of research that have proven to not be the issue.
SQL Statement too long?
This should not be an issue, because sys.fn_get_audit_file_transact_sql will wap the query and increment sequence_number
. See dzone.com article on sql-audit-not-showing-full-sql-statement for an example.
SQL Statement redacted?
This does not appear to be an issue either. Certain items, e.g. password changes, are redacted when logged in an audit. They are redacted with a series of *
marks. See sqlservercentral.com article on auditing password changes.
Audit definition
USE [master];GOCREATE SERVER AUDIT [AuditSELECT_123456789]TO FILE ( FILEPATH = N'x:\Audits\' ,MAXSIZE = 20 MB ,MAX_ROLLOVER_FILES = 2147483647 ,RESERVE_DISK_SPACE = OFF)WITH( QUEUE_DELAY = 1000 ,ON_FAILURE = CONTINUE ,AUDIT_GUID = 'd985d743-efb5-466f-be47-901b6a572753')ALTER SERVER AUDIT [AuditSELECT_123456789] WITH (STATE = ON);GOUse [DATABASENAME];GOCREATE DATABASE AUDIT SPECIFICATION [AuditSELECT_123456789]FOR SERVER AUDIT [AuditSELECT_123456789]ADD (DELETE ON DATABASE::[DATABASENAME] BY [USERNAME]),ADD (EXECUTE ON DATABASE::[DATABASENAME] BY [USERNAME]),ADD (INSERT ON DATABASE::[DATABASENAME] BY [USERNAME]),ADD (RECEIVE ON DATABASE::[DATABASENAME] BY [USERNAME]),ADD (SELECT ON DATABASE::[DATABASENAME] BY [USERNAME]),ADD (UPDATE ON DATABASE::[DATABASENAME] BY [USERNAME])WITH (STATE = ON);
Server info
Windows 2012r2 64 bit, SQL Server version 13.0.5865.1 Enterprise 64 bit, otherwise current on patches.
UDF and View psuedo code source
getkey udf
It executes as the caller
CREATE FUNCTION getkey(@p_key_name NVARCHAR(128))RETURNS VARCHAR(1024)WITH RETURNS NULL ON NULL INPUTASBEGINDECLARE @v_key_value VARCHAR(1024);SELECT @v_key_value = k.key FROM keystable k WHERE k.name = @p_key_name;RETURN @v_key_value;END;
view1
select * FROM table1 JOIN table2 JOIN table3 JOIN table4 JOIN otherdb.table5 JOIN table2 JOIN table1 JOIN table6 JOIN view2 JOIN table9 JOIN table9 JOIN table10 JOIN table11 JOIN view3 JOIN view4 JOIN table14
view2
SELECT * FROM table7 UNION SELECT * FROM table8
view3
select * FROM table12 JOIN table7 JOIN table7 JOIN table13 JOIN table7 JOIN table8
view4
select * FROM table15 JOIN table16 JOIN table17