How to audit DDL statements in SQL Sserver 2017 - sql-server

I have MicroSoft SQL Server 2017, I audited all DML statements using commands like
CREATE DATABASE AUDIT SPECIFICATION [DatabaseAuditSpecification-dbo-GENERAL]
FOR SERVER AUDIT [Audit-Primary-dbo]
ADD (DELETE ON SCHEMA::xxx BY [dbo]),
ADD (INSERT ON SCHEMA::xxx BY [dbo]),
ADD (UPDATE ON SCHEMA::xxx BY [dbo]),
ADD (SELECT ON SCHEMA::xxx BY [dbo]),
ADD (DELETE ON SCHEMA::xxx BY [db_datawriter]),
ADD (INSERT ON SCHEMA::xxx BY [db_datawriter]),
...
Now I've been asked to audit ALL what is done by dbo/datawriter users, such as:
table drop/create/change
schema changes (alter table add column, ...)
BUT ALSO
unsuccessful schema accesses (select on a table which is not authorized)
unsuccessful executions due to integrity violation rules
Questions:
Is there any "audit all" on database by dbo, datawriter possibility?
How to audit failed attempts?
Thanks

Related

SQL Server Database Auditing not working for Sysadmin users

I'm trying to Audit Sysadmin users at Database level; however, none of the SELECTS, INSERTS, UPDATES and DELETES are being audited.
I created the Server Audit, followed by the Server Audit specification
ADD (DATABASE_OBJECT_ACCESS_GROUP) and then the Database Audit specification to audit the database as a whole: ADD (SELECT, UPDATE, INSERT, DELETE, EXECUTE, RECEIVE, REFERENCES ON DATABASE::TestAuditDB BY newsa2);
I tested it by INSERTing and SELECTing with that user 'newsa2'; however, no audit entries were found.
I need very specific entries for each sysadmin user to be entered into the Audit log
Here is my code:
USE [master]
GO
DROP SERVER AUDIT [Audit_sql2016]
TO FILE
( FILEPATH = N'C:\Audit\SQL2016'
,MAXSIZE = 100 MB
,MAX_ROLLOVER_FILES = 2147483647
,RESERVE_DISK_SPACE = OFF
)
WITH
( QUEUE_DELAY = 1000
,ON_FAILURE = CONTINUE
);
GO
CREATE SERVER AUDIT SPECIFICATION [Audit_sql2016Specification]
FOR SERVER AUDIT [Audit_sql2016]
ADD (DATABASE_OBJECT_ACCESS_GROUP)
WITH (STATE = OFF);
GO
ALTER SERVER AUDIT SPECIFICATION [Audit_sql2016Specification]
FOR SERVER AUDIT [Audit_sql2016]
WITH (STATE = ON);
ALTER SERVER AUDIT Audit_sql2016 WITH (STATE = OFF)
GO
USE TestAuditDB
GO
DROP DATABASE AUDIT SPECIFICATION [Audit_sql2016SpecificationDatabase]
FOR SERVER AUDIT [Audit_sql2016]
ADD (SELECT, UPDATE, INSERT, DELETE, EXECUTE, RECEIVE, REFERENCES ON DATABASE::TestAuditDB BY newsa2);
ALTER DATABASE AUDIT SPECIFICATION [Audit_sql2016SpecificationDatabase]
--FOR SERVER AUDIT [Audit_sql2016]
WITH (STATE = ON);
I have adapted and fixed your script (there is a missing step to enable SERVER AUDIT - I noticed with SQL Server Management Studio where there was a red cross for related icon):
USE [master]
GO
ALTER SERVER AUDIT [audit_server] WITH (STATE=OFF)
GO
DROP SERVER AUDIT [audit_server]
GO
ALTER SERVER AUDIT SPECIFICATION [audit_spec] WITH (STATE = OFF)
GO
DROP SERVER AUDIT SPECIFICATION [audit_spec]
GO
CREATE SERVER AUDIT [audit_server]
TO FILE
( FILEPATH = 'C:\Audit'
)
WHERE database_name='test';
GO
ALTER SERVER AUDIT [audit_server] WITH (STATE = ON);
GO
CREATE SERVER AUDIT SPECIFICATION [audit_spec]
FOR SERVER AUDIT [audit_server]
WITH (STATE = OFF);
GO
ALTER SERVER AUDIT SPECIFICATION [audit_spec]
FOR SERVER AUDIT [audit_server]
ADD (DATABASE_OBJECT_ACCESS_GROUP)
WITH (STATE = ON);
USE Test
GO
ALTER DATABASE AUDIT SPECIFICATION [audit_db]
WITH (STATE = OFF);
GO
DROP DATABASE AUDIT SPECIFICATION [audit_db]
GO
CREATE DATABASE AUDIT SPECIFICATION [audit_db]
FOR SERVER AUDIT [audit_server]
ADD (SELECT, UPDATE, INSERT, DELETE, EXECUTE, RECEIVE, REFERENCES ON DATABASE::test by public);
GO
ALTER DATABASE AUDIT SPECIFICATION [audit_db]
WITH (STATE = ON);
GO
With this setup I can have in audit following DML statements run by user dbo in database test (corresponding login has sysadmin role):
use test
go
delete from t;
go
insert into t values(1);
go
Tested with SQL Server 2019.
You can audit only a specific schema with:
CREATE DATABASE AUDIT SPECIFICATION [audit_db]
FOR SERVER AUDIT [audit_server]
ADD (SELECT, UPDATE, INSERT, DELETE, EXECUTE, RECEIVE, REFERENCES ON SCHEMA::myschema by public);
GO
Should we add the SCHEMA_OBJECT_ACCESS_GROUP to the Audit Server specification? I want to audit only the dbo schema, as the sys schema audits are generating too much noise.
Ans: Not required. The DATABASE_OBJECT_ACCESS_GROUP takes care of this as well.

My query sys.database_audit_specification does't send back any record

I'm studying about SQL Server Audit. I have deployed Server Audit Specification. Now I want to query all the records but It doesn't return anything.
I use Windows Server 2012 Datacenter - SQL Server 2014 Developer Version
use master
go
select *
from sys.database_audit_specifications;
go
I got no output and don't understand why.
How can I fix it?
Here is an example that creates a server-level audit, then adds a database-level audit specification to track multiple operations on any object in the dbo schema.
USE master;
GO
-- create aserver audit
CREATE SERVER AUDIT Test_Server_Audit
TO FILE ( FILEPATH = 'C:\temp\' ); -- you may need to change that'
GO
-- turn it on
ALTER SERVER AUDIT Test_Server_Audit WITH (STATE = ON);
GO
-- create a demo database
CREATE DATABASE floob;
GO
USE floob;
GO
CREATE TABLE dbo.blat(x INT);
GO
-- create a database audit specification that monitors for activity
-- against any dbo object:
CREATE DATABASE AUDIT SPECIFICATION Test_Database_Audit
FOR SERVER AUDIT Test_Server_Audit
ADD (SELECT, UPDATE, DELETE, INSERT, EXECUTE ON SCHEMA::dbo BY PUBLIC)
WITH (STATE = ON);
GO
-- do a couple of things:
SELECT * FROM dbo.blat;
DELETE dbo.blat;
GO
-- you should see those couple of things in the audit file:
SELECT * FROM sys.fn_get_audit_file('C:\temp\*.sqlaudit', NULL, NULL);
GO
For Further Reading follow this

What explicit permission am I missing that is preventing the effective INSERT permission at the table level?

I have a user that cannot update stored procedures because he gets an error that an INSERT cannot be done on one of our changelog tables. We checked his permissions to insert on that table and he has it, so we were confused as to why he couldn't insert. When we dug deep into this, it looks like we gave him the explicit permission to insert into the table, but for some reason he does not list INSERT as an effective permission. Our layout is server -> database -> table (pretty simple setup).
Note - for some reason when writing this question, it kept interpreting my inserted pictures as code and wouldn't let me post with embedded pics, so I had to use links instead.
Explicit server permissions:
ALTER ANY DATABASE
CONNECT SQL
CREATE ANY DATABASE
Effective server permissions:
ALTER ANY DATABASE
CONNECT SQL
CREATE ANY DATABASE
VIEW ANY DATABASE
VIEW ANY DEFINITION
Explicit database permissions:
ALTER
CONNECT
CREATE TABLE
DELETE
INSERT
SELECT
SHOW PLAN
UPDATE
VIEW DEFINITION
Effective database permissions:
Explicit table permissions:
ALTER
CONTROL
DELETE
INSERT
REFERENCES
SELECT
TAKE OWNERSHIP
UPDATE
VIEW CHANGE TRACKING
VIEW DEFINITION
Effective table permissions:

SQL Server Audits

im trying to setup a GDPR-Compliant auditing system for our Databases in order to log reading or DML operations in certain tables.
I've read the MS documentation about SQL Auditing and actually didnt found anything helpful about my problem, which comes when queries or data requests come from application users.
If i run a select on dbo.DevContent1 (even with SA or using my own login) it is recorded,
but If the same query runs in application code, nothing new appears in SQL Audit logs
Here is my current Audit specifications configuration:
USE [MY_DEV_DB]
GO
CREATE DATABASE AUDIT SPECIFICATION [GDPR_DEV_Audits]
FOR SERVER AUDIT [GDPR_PDATA_Audit]
ADD (DELETE ON OBJECT::[dbo].[DevContent1] BY [dbo]),
ADD (INSERT ON OBJECT::[dbo].[DevContent1] BY [dbo]),
ADD (SELECT ON OBJECT::[dbo].[DevContent1] BY [dbo]),
ADD (UPDATE ON OBJECT::[dbo].[DevContent1] BY [dbo]),
ADD (DELETE ON OBJECT::[dbo].[DevCustomer1] BY [dbo]),
ADD (INSERT ON OBJECT::[dbo].[DevCustomer1] BY [dbo]),
ADD (SELECT ON OBJECT::[dbo].[DevCustomer1] BY [dbo]),
ADD (UPDATE ON OBJECT::[dbo].[DevCustomer1] BY [dbo]),
ADD (DELETE ON OBJECT::[dbo].[DevQuotes] BY [dbo]),
ADD (INSERT ON OBJECT::[dbo].[DevQuotes] BY [dbo]),
ADD (SELECT ON OBJECT::[dbo].[DevQuotes] BY [dbo]),
ADD (UPDATE ON OBJECT::[dbo].[DevQuotes] BY [dbo]),
ADD (DELETE ON OBJECT::[dbo].[DevUsers] BY [dbo]),
ADD (INSERT ON OBJECT::[dbo].[DevUsers] BY [dbo]),
ADD (SELECT ON OBJECT::[dbo].[DevUsers] BY [dbo]),
ADD (UPDATE ON OBJECT::[dbo].[DevUsers] BY [dbo])
WITH (STATE = ON)
GO
Any idea about how to solve this?
Thanks
The reason that the audit isn't working for your application user, is because the Audit has been set up specifically for the user [dbo]:
CREATE DATABASE AUDIT SPECIFICATION [GDPR_DEV_Audits]
FOR SERVER AUDIT [GDPR_PDATA_Audit]
ADD (DELETE ON OBJECT::[dbo].[DevContent1] BY [dbo]);
I doubt that your applicaiton login maps to the user [dbo]; as [dbo]is the database owner (and thus would have very elevated permissions).
I believe if you want to audit all users on the database you need to use BY [public], as every user should be a member of this role. Thus:
CREATE DATABASE AUDIT SPECIFICATION [GDPR_DEV_Audits]
FOR SERVER AUDIT [GDPR_PDATA_Audit]
ADD (DELETE ON OBJECT::[dbo].[DevContent1] BY [public]);
If you do have any users not a member of public, you'll need to add those users (or the roles) separately; or add them to the public role again.

How to get the network user who is executing the transaction

I got a task from my customer on his existing SQL Server database.
They have a database with 1 user with all admin rights. They manage the accessibility rights on the application level.
The task is to create an audit table, to audit who INSERT, UPDATE, & DELETE from database tables.
The structure of this table is simple:
TableName
Operation {INSERT, UPDATE, or DELETE}
TimeStamp,
UserName
The audit log is requested to be on server side through triggers.
So it is an EASY Task: Add Trigger to each table & each Event. Inside the trigger, insert a new row to Audit Table with Values of (TableName, Operation, TimeStamp, & UserName).
The problem is the username (SQL: SYSTEM_USER) is always the same for all users as they all connect with the same admin account.
Is there anyway, in SQL server, to get the network user name who is making the transaction?
I am sorry I should have made some researches before asking. Anyway, it could be useful to others.
I found this function [Host_Name()], which returns the name of the computer that makes the transaction.

Resources