Select any two versions of this STIG to compare the individual requirements
Select any old version/release of this STIG to view the previous requirements
Determine if Azure SQL Database is configured to use Azure Active Directory authentication only. Only Azure Active Directory will be used to authenticate to the server. SQL authentication will be disabled, including SQL Server administrators and users. In a PowerShell or Cloud Shell interface, run the statement: az sql server ad-only-auth get --resource-group myresource --name myserver OR Get-AzSqlServerActiveDirectoryOnlyAuthentication -ServerName myserver -ResourceGroupName myresource If the returned value in the "AzureADOnlyAuthentication" column is "True", this is not a finding. If Mixed mode (both SQL Server authentication and Windows authentication) is in use and the need for mixed mode has not been documented and approved, this is a finding. From the documentation, obtain the list of accounts authorized to be managed by Azure SQL Database. Determine the accounts (SQL Logins) actually managed by Azure SQL Database. Run the statement: SELECT name FROM sys.database_principals WHERE type_desc = 'SQL_USER' AND authentication_type_desc = 'INSTANCE'; If any accounts listed by the query are not listed in the documentation, this is a finding. Risk must be accepted by the ISSO/ISSM. More information regarding this process is available at: https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication
If mixed mode is required, document the need and justification; describe the measures taken to ensure the use of Azure SQL Database authentication is kept to a minimum; describe the measures taken to safeguard passwords; list or describe the SQL Logins used; and obtain official approval. If mixed mode is not required: For each account being managed by SQL DB but not requiring it, drop or disable the SQL Database user. Replace it with an appropriately configured account, as needed. To drop a User in the SSMS Object Explorer: Navigate to Databases, choose database, then select Security >> Users. Right-click on the User name and then click "Delete". To drop a User via a query: Change the context to the database_name to be evaluates; DROP USER <user_name>; To enable AzureADOnlyAuthentication, in a PowerShell or Cloud Shell interface, run the statement: az sql server ad-only-auth enable --resource-group myresource --name myserver OR Enable-AzSqlServerActiveDirectoryOnlyAuthentication -ServerName myserver -ResourceGroupName myresource More information regarding this process is available at: https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication
Review the system documentation to determine the required levels of protection for securables in the database, by type of user. Review the permissions actually in place in the database. Execute the following query to find permissions assigned: SELECT DISTINCT [Finding] = 'Database ' + QUOTENAME(DB_NAME()) + ' ' + CASE WHEN dbp.type = 'r' THEN 'Role ' ELSE 'User ' END + QUOTENAME(dbp.name) + CASE WHEN dbp.type = 'r' THEN ' owning schema ' ELSE ' in db role ' END + QUOTENAME(ISNULL(dbp2.name,'-')) + ' has db permission ' + QUOTENAME(ISNULL(dbper.permission_name,'-')) -- + ' on object ' + QUOTENAME(ISNULL(OBJECT_NAME(dbper.major_id),'-')) + ' on object ' + QUOTENAME(ISNULL(CASE WHEN dbper.major_id = 0 THEN 'Database' ELSE OBJECT_NAME(dbper.major_id) END,'-')) + '.' COLLATE SQL_Latin1_General_CP1_CI_AS FROM sys.database_principals dbp LEFT JOIN sys.database_role_members dbrm ON dbp.principal_Id = dbrm.member_principal_Id LEFT JOIN sys.database_principals dbp2 ON dbrm.role_principal_id = dbp2.principal_id LEFT JOIN sys.database_permissions dbper ON dbper.grantee_principal_id = dbp.principal_id WHERE dbp.type IN ('u','s','g','r') /*Windows/Sql/Groups */ AND NOT (dbp.name = 'public' AND dbper.permission_name IN ('select','execute') AND DB_NAME() = 'master') /*ignore public permissions in master*/ AND NOT (dbp.name = 'public' AND dbper.permission_name IN ('select','execute') AND OBJECT_SCHEMA_NAME(major_id, DB_ID()) = 'sys') AND ( /*Filter out duplicate permissions in each database except for the base master database*/ dbp2.name IS NOT NULL /* This seems to filter out permissions granted to a role.*/ AND dbper.permission_name IS NOT NULL AND dbper.major_id IS NOT NULL OR DB_NAME() = 'master') If the actual permissions do not match the documented requirements, this is a finding.
Use GRANT, REVOKE, DENY, ALTER ROLE … ADD MEMBER … and/or ALTER ROLE …. DROP MEMBER statements to add and remove permissions on database-level securables, bringing them in line with the documented requirements. References: Revoke: https://docs.microsoft.com/en-us/sql/t-sql/statements/revoke-transact-sql?view=azuresqldb-current Deny: https://docs.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql?view=azuresqldb-current DROP MEMBER: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-droprolemember-transact-sql?view=azuresqldb-current
Review the system documentation to determine the required levels of protection for DBMS server securables, by type of login. Review the permissions actually in place on the server. Execute the following query to find permissions in place on the server: SELECT DISTINCT QUOTENAME(sp.name) + ' in server role ' + QUOTENAME(ISNULL(sp2.name,'Public')) + ' has ' + QUOTENAME(ISNULL(class_desc,'server'))+ ':' + QUOTENAME(ISNULL(object_name(major_id),'~')) + ' permission ' + QUOTENAME(ISNULL(srvper.permission_name,'-')) + '.' COLLATE SQL_Latin1_General_CP1_CI_AS Finding , object_name(major_id) ObjectName FROM sys.database_principals sp LEFT JOIN sys.database_role_members srm ON sp.principal_id = srm.member_principal_id LEFT JOIN sys.database_principals sp2 ON srm.role_principal_id = sp2.principal_id LEFT JOIN sys.database_permissions srvper ON srvper.grantee_principal_id = sp.principal_id WHERE sp.type IN ('u','s','g') --Windows/Sql/Groups AND sp.principal_id <> 1 If the actual permissions do not match the documented requirements, this is a finding.
Use GRANT, REVOKE, DENY, ALTER SERVER ROLE … ADD MEMBER … and/or ALTER SERVER ROLE …. DROP MEMBER statements to add and remove permissions on server-level securables, bringing them in line with the documented requirements. References: Revoke: https://docs.microsoft.com/en-us/sql/t-sql/statements/revoke-transact-sql?view=azuresqldb-current Deny: https://docs.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql?view=azuresqldb-current DROP MEMBER: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-droprolemember-transact-sql?view=azuresqldb-current
Obtain the list of authorized Azure SQL Database accounts in the system documentation. Determine if any accounts are shared. A shared account is defined as a username and password that are used by multiple individuals to log in to Azure SQL Database. Azure Active Directory accounts are not shared accounts as the group itself does not have a password. If accounts are determined to be shared, determine if individuals are first individually authenticated. If individuals are not individually authenticated before using the shared account (e.g., by the operating system or possibly by an application making calls to the database), this is a finding. The key is individual accountability. If this can be traced, this is not a finding. If accounts are determined to be shared, determine if they are directly accessible to end users. If so, this is a finding. Review contents of audit logs and data tables to confirm that the identity of the individual user performing the action is captured. If shared identifiers are found and not accompanied by individual identifiers, this is a finding.
Remove user-accessible shared accounts and use individual user IDs. Build/configure applications to ensure successful individual authentication prior to shared account access. Ensure each user's identity is received and used in audit data in all relevant circumstances. Design, develop, and implement a method to log use of any account to which more than one person has access. Restrict interactive access to shared accounts to the fewest persons possible.
Check the server documentation to determine if collecting and keeping historical versions of a table is required. If collecting and keeping historical versions of a table is NOT required, this is not a finding. Find all of the temporal tables in the database using the following query: SELECT SCHEMA_NAME(T.schema_id) AS schema_name, T.name AS table_name, T.temporal_type_desc, SCHEMA_NAME(H.schema_id) + '.' + H.name AS history_table FROM sys.tables T JOIN sys.tables H ON T.history_table_id = H.object_id WHERE T.temporal_type != 0 ORDER BY schema_name, table_name Using the system documentation, determine which tables are required to be temporal tables. If any tables listed in the documentation are not in the list created by running the above statement, this is a finding. Ensure a field exists documenting the login and/or user who last modified the record. If this does not exist, this is a finding. Review the system documentation to determine the history retention period. Navigate to the table in Object Explorer. Right-click on the table, and then select Script Table As >> CREATE To >> New Query Editor Window. Locate the line that contains "SYSTEM_VERSIONING". Locate the text that states "HISTORY_RETENTION_PERIOD". If this text is missing, or is set to a value less than the documented history retention period, this is a finding.
Alter sensitive tables to utilize system versioning. --Alter non-temporal table to define periods for system versioning ALTER TABLE <MyTableName> ADD PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime), SysStartTime datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL DEFAULT SYSUTCDATETIME(), SysEndTime datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.99999999') ; --Enable system versioning with 1 year retention for historical data ALTER TABLE <MyTableName> SET (SYSTEM_VERSIONING = ON (HISTORY_RETENTION_PERIOD = 1 YEAR)) ; https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-table-transact-sql?view=azuresqldb-current#system_versioning
Review system documentation to identify Azure SQL Database accounts authorized to own database objects. If the Azure SQL Database ownership list does not exist or needs to be updated, this is a finding. The following query can be of use in making this determination: ;with objects_cte as (SELECT o.name, o.type_desc, CASE WHEN o.principal_id is null then s.principal_id ELSE o.principal_id END as principal_id FROM sys.objects o INNER JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE o.is_ms_shipped = 0 ) SELECT cte.name, cte.type_desc, dp.name as ObjectOwner FROM objects_cte cte INNER JOIN sys.database_principals dp ON cte.principal_id = dp.principal_id ORDER BY dp.name, cte.name If any of the listed owners is not authorized, this is a finding.
Document and obtain approval for any account(s) authorized for object ownership. If necessary, use the ALTER AUTHORIZATION command to change object ownership to an authorized account. Example provided below. ALTER AUTHORIZATION ON OBJECT::test.table TO AuthorizedUser; https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql
Obtain a listing of users and roles who are authorized to modify database structure and logic modules from the server documentation. Execute the following query to obtain a list of database principals: SELECT P.type_desc AS principal_type, P.name AS principal_name, O.type_desc, CASE class WHEN 0 THEN DB_NAME() WHEN 1 THEN OBJECT_SCHEMA_NAME(major_id) + '.' + OBJECT_NAME(major_id) WHEN 3 THEN SCHEMA_NAME(major_id) ELSE class_desc + '(' + CAST(major_id AS nvarchar) + ')' END AS securable_name, DP.state_desc, DP.permission_name FROM sys.database_permissions DP JOIN sys.database_principals P ON DP.grantee_principal_id = P.principal_id LEFT OUTER JOIN sys.all_objects O ON O.object_id = DP.major_id AND O.type IN ('TR','TA','P','X','RF','PC','IF','FN','TF','U') WHERE DP.type IN ('AL','ALTG') AND DP.class IN (0, 1, 53) Execute the following query to obtain a list of role memberships: SELECT R.name AS role_name, M.type_desc AS principal_type, M.name AS principal_name FROM sys.database_principals R JOIN sys.database_role_members DRM ON R.principal_id = DRM.role_principal_id JOIN sys.database_principals M ON DRM.member_principal_id = M.principal_id WHERE R.name IN ('db_ddladmin','db_owner') AND M.name != 'dbo' If unauthorized access to the principal(s)/role(s) has been granted, this is a finding.
Document and obtain approval for any nonadministrative user(s) who require the ability to modify database structure and logic modules. If necessary, use the ALTER ROLE and/or REVOKE commands to remove unauthorized users access to modify database structure. Examples provided below. ALTER ROLE ddladmin DROP MEMBER UnauthorizedUser; REVOKE SELECT ON OBJECT::test.table FROM UnauthorizedUser; https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-role-transact-sql https://docs.microsoft.com/en-us/sql/t-sql/statements/revoke-transact-sql
Determine elements of security functionality (lists of permissions, additional authentication information, stored procedures, application specific auditing, etc.) being housed inside Azure SQL Database. For any elements found, check Azure SQL Database to determine if these objects or code implementing security functionality are located in a separate security domain, such as a separate database, schema, or table created specifically for security functionality. Review the database structure to determine where security related functionality is stored. If security-related database objects or code are not kept separate, this is a finding.
Check the server documentation, locate security-related database objects and code in a separate database, schema, table, or other separate security domain from database objects and code implementing application logic. Schemas are analogous to separate namespaces or containers used to store database objects. Security permissions apply to schemas, making them an important tool for separating and protecting database objects based on access rights. Schemas reduce the work required, and improve the flexibility, for security-related administration of a database. User-schema separation allows for more flexibility in managing database object permissions. A schema is a named container for database objects, which allows the user group objects into separate namespaces. Where possible, locate security-related database objects and code in a separate database, schema, or other separate security domain from database objects and code implementing application logic. In all cases, use GRANT, REVOKE, DENY, ALTER ROLE … ADD MEMBER … and/or ALTER ROLE …. DROP MEMBER statements to add and remove permissions on server-level and database-level security-related objects to provide effective isolation.
Review the procedures for the refreshing of development/test data from production. Review any scripts or code that exists for the movement of production data to development/test systems, or to any other location or for any other purpose. Verify that copies of production data are not left in unprotected locations. If the code that exists for data movement does not comply with the organization-defined data transfer policy and/or fails to remove any copies of production data from unprotected locations, this is a finding.
Modify any code used for moving data from production to development/test systems to comply with the organization-defined data transfer policy, and to ensure copies of production data are not left in unsecured locations.
Review Azure SQL Database code (stored procedures, functions, triggers), application code, settings, column and field definitions, and constraints to determine whether the database is protected against invalid input. If code exists that allows invalid data to be acted upon or input into the database, this is a finding. If column/field definitions are not reflective of the data, this is a finding. If columns/fields do not contain constraints and validity checking where required, this is a finding. Where a column/field is noted in the system documentation as necessarily free-form, even though its name and context suggest that it should be strongly typed and constrained, the absence of these protections is not a finding. Where a column/field is clearly identified by name, caption or context as Notes, Comments, Description, Text, etc., the absence of these protections is not a finding.
Use parameterized queries, constraints, foreign keys, etc., to validate data input. Modify Azure SQL Database to properly use the correct column data types as required in the database.
Review the system documentation to obtain a listing of stored procedures and functions that utilize dynamic code execution. Execute the following query: DECLARE @tblDynamicQuery TABLE (ID INT identity(1,1), ProcToExecuteDynSQL VARCHAR(500)) INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('EXEC[ (]@') INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('EXECUTE[ (]@') INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('SP_EXECUTESQL[ (]@') SELECT QUOTENAME(DB_Name()) DB_Name, QUOTENAME(SCHEMA_NAME([schema_id])) + '.' + QUOTENAME(name) Name, QUOTENAME(type_desc) ObjectType FROM sys.objects o WHERE o.is_ms_shipped = 0 and o.object_id IN ( SELECT m.object_id FROM sys.sql_modules m JOIN @tblDynamicQuery dsql ON REPLACE(REPLACE(REPLACE(m.definition,CHAR(32),'()'),')(',''),'()',CHAR(32)) like '%' + dsql.ProcToExecuteDynSQL + '%') If any procedures or functions are returned that are not documented, this is a finding.
Where dynamic code execution is employed in circumstances where the objective could practically be satisfied by static execution with strongly typed parameters, modify the code to do so.
Review the system documentation to obtain a listing of stored procedures and functions that utilize dynamic code execution. Execute the following query: DECLARE @tblDynamicQuery TABLE (ID INT identity(1,1), ProcToExecuteDynSQL VARCHAR(500)) INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('EXEC[ (]@') INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('EXECUTE[ (]@') INSERT INTO @tblDynamicQuery(ProcToExecuteDynSQL) values('SP_EXECUTESQL[ (]@') SELECT QUOTENAME(DB_Name()) DB_Name, QUOTENAME(SCHEMA_NAME([schema_id])) + '.' + QUOTENAME(name) Name, QUOTENAME(type_desc) ObjectType FROM sys.objects o WHERE o.is_ms_shipped = 0 and o.object_id IN ( SELECT m.object_id FROM sys.sql_modules m JOIN @tblDynamicQuery dsql ON REPLACE(REPLACE(REPLACE(m.definition,CHAR(32),'()'),')(',''),'()',CHAR(32)) like '%' + dsql.ProcToExecuteDynSQL + '%') If any procedures or functions are returned that are not documented, this is a finding.
Where dynamic code execution is used, modify the code to implement protections against code injection.
If security labeling is not required, this is not a finding. If security labeling requirements have been specified, but a third-party solution, SQL Information Protection, or an Azure SQL Database Row-Level security solution is implemented that reliably maintains labels on information in storage, this is a finding.
Deploy SQL Information Protection (see link below) or Azure SQL Database Row-Level Security (see link below), a third-party software, or add custom data structures, data elements and application code to provide reliable security labeling of information in storage. https://docs.microsoft.com/en-us/azure/security-center/security-center-info-protection-policy? https://msdn.microsoft.com/en-us/library/dn765131.aspx
If security labeling is not required, this is not a finding. If security labeling requirements have been specified, but a third-party solution, SQL Information Protection, or an Azure SQL Database Row-Level security solution is implemented that reliably maintains labels on information in process, this is a finding.
Deploy SQL Information Protection (see link below) or Azure SQL Database Row-Level Security (see link below), a third-party software, or add custom data structures, data elements and application code to provide reliable security labeling of information in process. https://docs.microsoft.com/en-us/azure/security-center/security-center-info-protection-policy? https://msdn.microsoft.com/en-us/library/dn765131.aspx
If security labeling is not required, this is not a finding. If security labeling requirements have been specified, but a third-party solution, SQL Information Protection, or an Azure SQL Database Row-Level security solution is implemented that reliably maintains labels on information in transmission, this is a finding.
Deploy SQL Information Protection (see link below) or Azure SQL Database Row-Level Security (see link below), a third-party software, or add custom data structures, data elements and application code to provide reliable security labeling of information in transmission. https://docs.microsoft.com/en-us/azure/security-center/security-center-info-protection-policy? https://msdn.microsoft.com/en-us/library/dn765131.aspx
Review application or system documentation to identify the required DAC. Review the security configuration of the database. If applicable, review the security configuration of the application(s) using the database. If the DAC defined in the documentation is not implemented in the security configuration, this is a finding. Validate database object ownership using the queries below: View object ownership - All objects and schemas SELECT object_id, SCHEMA_NAME(schema_id) AS SchemaName, [name] AS Securable, USER_NAME(principal_id) AS ObjectOwner, [type_desc] AS ObjectType FROM sys.objects WHERE is_ms_shipped = 0 AND principal_id IS NOT NULL ORDER BY ObjectType, Securable, ObjectOwner View object ownership - Specific object DECLARE @ObjectName nvarchar(512) SET @ObjectName = '' --Specify object name here SELECT object_id, SCHEMA_NAME(schema_id) AS SchemaName, [name] AS Securable, USER_NAME(principal_id) AS ObjectOwner, [type_desc] AS ObjectType FROM sys.objects WHERE is_ms_shipped = 0 AND principal_id IS NOT NULL AND [name] = @ObjectName ORDER BY ObjectType, Securable, ObjectOwner View object ownership - Specific schema DECLARE @SchemaName nvarchar(512) SET @SchemaName = '' --Specify schema name here SELECT object_id, SCHEMA_NAME(schema_id) AS SchemaName, [name] AS Securable, USER_NAME(principal_id) AS ObjectOwner, [type_desc] AS ObjectType FROM sys.objects WHERE is_ms_shipped = 0 AND principal_id IS NOT NULL AND SCHEMA_NAME(schema_id) = @SchemaName ORDER BY ObjectType, Securable, ObjectOwner Schemas not owned by the schema or [dbo] SELECT [name] AS [SchemaName], USER_NAME(principal_id) AS [SchemaOwner] FROM sys.schemas WHERE schema_id != principal_id --exclude schemas owned by the schema AND principal_id != 1 --exclude schema dbo Database principals delegated the right to assign additional permissions SELECT U.type_desc AS [PrincipalType], U.name AS [Grantee], DP.class_desc AS [SecurableType], CASE DP.class WHEN 0 THEN DB_NAME() WHEN 1 THEN OBJECT_NAME(DP.major_id) WHEN 3 THEN SCHEMA_NAME(DP.major_id) ELSE CAST(DP.major_id AS nvarchar) END AS [Securable], permission_name AS [PermissionName], state_desc AS [DelegatedRight] FROM sys.database_permissions DP JOIN sys.database_principals U ON DP.grantee_principal_id = U.principal_id WHERE DP.state = 'W' ORDER BY Grantee, SecurableType, Securable If any of these rights are not documented and authorized, this is a finding.
To correct object ownership: Use the ALTER AUTHORIZATION ON::[Object Name] TO [Database principal] TSQL statement to correct object ownership. Full ALTER AUTHORIZATION command syntax is described in this document: ALTER AUTHORIZATION (Transact-SQL) - SQL Server | Microsoft Docs (https://docs.microsoft.com/en-us/sql/t-sql/statements/revoke-transact-sql?view=azuresqldb-current) To remove unauthorized permissions: Use the REVOKE [Permission name] ON [Object name] TO [Database principal] to remove unauthorized permissions from a database principal on an object. Full REVOKE command syntax is described in this document: REVOKE (Transact-SQL) - SQL Server | Microsoft Docs (https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql?view=azuresqldb-current)
Review the system documentation to obtain a listing of stored procedures and functions that utilize impersonation. Execute the following query: SELECT S.name AS schema_name, O.name AS module_name, USER_NAME(CASE M.execute_as_principal_id WHEN -2 THEN COALESCE(O.principal_id, S.principal_id) ELSE M.execute_as_principal_id END) AS execute_as FROM sys.sql_modules M JOIN sys.objects O ON M.object_id = O.object_id JOIN sys.schemas S ON O.schema_id = S.schema_id WHERE execute_as_principal_id IS NOT NULL ORDER BY schema_name, module_name If any procedures or functions are returned that are not documented, this is a finding.
Alter stored procedures and functions to remove the "EXECUTE AS" statement.
If the Azure SQL Database supports only software development, experimentation and/or developer-level testing (that is, excluding production systems, integration testing, stress testing, and user acceptance testing), this is not a finding. Obtain a listing of users and roles who are authorized to create, alter, or replace logic modules from the server documentation. Execute the following query to obtain a list of database principals: SELECT P.type_desc AS principal_type, P.name AS principal_name, O.type_desc, CASE class WHEN 0 THEN DB_NAME() WHEN 1 THEN OBJECT_SCHEMA_NAME(major_id) + '.' + OBJECT_NAME(major_id) WHEN 3 THEN SCHEMA_NAME(major_id) ELSE class_desc + '(' + CAST(major_id AS nvarchar) + ')' END AS securable_name, DP.state_desc, DP.permission_name FROM sys.database_permissions DP JOIN sys.database_principals P ON DP.grantee_principal_id = P.principal_id LEFT OUTER JOIN sys.all_objects O ON O.object_id = DP.major_id AND O.type IN ('TR','TA','P','X','RF','PC','IF','FN','TF','U') WHERE DP.type IN ('AL','ALTG') AND DP.class IN (0, 1, 53) Execute the following query to obtain a list of role memberships: SELECT R.name AS role_name, M.type_desc AS principal_type, M.name AS principal_name FROM sys.database_principals R JOIN sys.database_role_members DRM ON R.principal_id = DRM.role_principal_id JOIN sys.database_principals M ON DRM.member_principal_id = M.principal_id WHERE R.name IN ('db_ddladmin','db_owner') AND M.name != 'dbo' If unauthorized access to the principal(s)/role(s) has been granted, this is a finding.
Document and obtain approval for any nonadministrative users who require the ability to create, alter, or replace logic modules. Revoke the ALTER permission from unauthorized users and roles: REVOKE ALTER ON [<Object Name>] TO [<Principal Name>]
Obtain a list of logins who have privileged permissions and role memberships in the data and control planes of Azure SQL Database. For Database Permissions: SELECT P.type_desc AS principal_type, P.name AS principal_name, O.type_desc, CASE class WHEN 0 THEN DB_NAME() WHEN 1 THEN OBJECT_SCHEMA_NAME(major_id) + '.' + OBJECT_NAME(major_id) WHEN 3 THEN SCHEMA_NAME(major_id) ELSE class_desc + '(' + CAST(major_id AS nvarchar) + ')' END AS securable_name, DP.state_desc, DP.permission_name FROM sys.database_permissions DP JOIN sys.database_principals P ON DP.grantee_principal_id = P.principal_id LEFT OUTER JOIN sys.all_objects O ON O.object_id = DP.major_id AND O.type IN ('TR','TA','P','X','RF','PC','IF','FN','TF','U') WHERE DP.type IN ('AL','ALTG') AND DP.class IN (0, 1, 53) For Database Role Memberships: SELECT R.name AS role_name, M.type_desc AS principal_type, M.name AS principal_name FROM sys.database_principals R JOIN sys.database_role_members DRM ON R.principal_id = DRM.role_principal_id JOIN sys.database_principals M ON DRM.member_principal_id = M.principal_id AND M.name != 'dbo' For Control Plane Role Memberships, run in PowerShell: $AzureSqlDbName = '<Azure SQL Database Name>' $AzureSqlDbResourceID = Get-AzResource -Name $AzureSqlDbName Get-AzRoleAssignment -Scope $AzureSqlDbResourceID.ResourceId -IncludeClassicAdministrators | Format-Table DisplayName,RoleDefinitionName Check the documentation to verify the logins and roles returned are authorized. If the logins and/or roles are not documented and authorized, this is a finding.
Document and obtain approval for logins with privileged permissions and role memberships. If necessary, use the ALTER ROLE and/or REVOKE commands to remove unauthorized privileged permissions and/or role memberships. Example provided below. ALTER ROLE ddladmin DROP MEMBER UnauthorizedUser; REVOKE SELECT ON OBJECT::test.table FROM UnauthorizedUser; https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-role-transact-sql https://docs.microsoft.com/en-us/sql/t-sql/statements/revoke-transact-sql If necessary, in the Azure Portal, navigate to the Access Control pane for the Azure SQL Database to review and remove unauthorized privileged permissions and/or role memberships. Refer to link to documentation below. https://docs.microsoft.com/en-us/azure/role-based-access-control/role-definitions-list https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-remove
Use the TSQL query below to determine database encryption state: SELECT DB_NAME(database_id) AS DatabaseName, encryption_state_desc AS EncryptionState, key_algorithm+CAST(key_length AS nvarchar(128)) AS EncryptionAlgorithm, encryptor_type FROM sys.dm_database_encryption_keys Validate that for each database the [EncryptionState] is "ENCRYPTED" and the [EncryptionAlgorithm] returns one of the following values: [AES128], [AES192], or [AES256]. If any other value is returned for either the [EncryptionState] or [EncryptionAlgorithm], this is a finding.
Use the ALTER DATABASE command to enable encryption on the database. ALTER DATABASE [Database Name Between Brackets] SET ENCRYPTION ON
Review the system documentation to determine whether the organization has defined the information at rest that is to be protected from modification, which must include, at a minimum, PII and classified information. If no information is identified as requiring such protection, this is not a finding. Review the configuration of the Azure SQL Database to ensure data at rest protections are implemented. If any of the information defined as requiring cryptographic protection from modification is not encrypted in a manner that provides the required level of protection, this is a finding. Retrieve Transparent Data Encryption status: $LogicalServerName = "myServer" $RGname = "myRG" $DBName = "myDatabase" Get-AzSqlDatabaseTransparentDataEncryption -ServerName $LogicalServerName -ResourceGroupName $RGname -DatabaseName $DBname Validate that Azure SQL Database Transparent Data Encryption (TDE) is enabled. If TDE is disabled, this is a finding.
If Azure SQL Database Transparent Data Encryption is disabled, use the Set-AzSqlDatabaseTransparentDataEncryption command to enable. $LogicalServerName = "myServer" $RGname = "myRG" $DBname = "myDatabase" $TDEstate = "Enabled" Set-AzSqlDatabaseTransparentDataEncryption -ResourceGroupName $RGname -ServerName $LogicalServerName -DatabaseName $DBname -State $TDEstate
Review the system documentation to determine whether the organization has defined the information at rest that is to be protected from modification, which must include, at a minimum, PII and classified information. If no information is identified as requiring such protection, this is not a finding. Review the configuration of the Azure SQL Database to ensure data at rest protections are implemented. If any of the information defined as requiring cryptographic protection from modification is not encrypted in a manner that provides the required level of protection, this is a finding. Retrieve Transparent Data Encryption status: $LogicalServerName = "myServerName" $RGname = "myResourceGroup" $DBName = "myDatabaseName" Get-AzSqlDatabaseTransparentDataEncryption -ServerName $LogicalServerName -ResourceGroupName $RGname -DatabaseName $DBname
If Azure SQL Database Transparent Data Encryption is disabled, use the Set-AzSqlDatabaseTransparentDataEncryption command to enable. $LogicalServerName = "myServerName" $RGname = "myResourceGroup" $DBName = "myDatabaseName" $TDEstate = "Enabled" Set-AzSqlDatabaseTransparentDataEncryption -ResourceGroupName $RGname -ServerName $LogicalServerName -DatabaseName $DBname -State $TDEstate
Review DBMS code (stored procedures, functions, triggers), application code, settings, column and field definitions, and constraints to determine whether the database is protected against invalid input. If code exists that allows invalid data to be acted upon or input into the database, this is a finding. If column/field definitions are not reflective of the data, this is a finding. If columns/fields do not contain constraints and validity checking where required, this is a finding. Where a column/field is noted in the system documentation as necessarily free-form, even though its name and context suggest that it should be strongly typed and constrained, the absence of these protections is not a finding. Where a column/field is clearly identified by name, caption or context as Notes, Comments, Description, Text, etc., the absence of these protections is not a finding.
Use parameterized queries, stored procedures, constraints and foreign keys to validate data input. Modify Azure SQL Database to properly use the correct column data types as required in the database.
Check Azure SQL Database to see if an auditing is enabled. Execute the following steps: 1. In the Azure Portal, open a Cloud Shell session. 2. Run this PowerShell command to determine if SQL Auditing is enabled: $ResourceGroup = "myResourceGroup" $ServerName = "myServerName" Get-AzSqlServerAudit -ResourceGroupName $ResourceGroup -ServerName $ServerName ` | Select-object -property BlobStorageTargetState,LogAnalyticsTargetState,EventHubTargetState If BlobStorageTargetState, LogAnalyticsTargetState and EventHubTargetState (all three) are Disabled, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script.
Obtain the list of approved audit maintainers from the system documentation. If any role memberships are not documented and authorized, this is a finding. Review the Azure roles and individual users, all of which enable the ability to create and maintain audits. To review the Azure roles and users, navigate to the Azure Portal and review the Azure Server controlling the Azure SQL Database. 1. Select "Access Control (IAM)". 2. Select "Role assignments" and review the roles assigned to each user. 3. Select "Roles", and then select "View" under the Details column for each role. Any roles or users with Write permissions to the auditing policy must be documented. This may include but is not limited to the Owner, Contributor, and Administrator roles. If any of the roles or users have permissions that are not documented, or the documented audit maintainers do not have permissions, this is a finding.
Create an Azure role specifically for audit maintainers, and give it write permissions to audit related permissions in the portal, without granting it unnecessary permissions. The role name used here is an example; other names may be used: Audit permissions are managed through the Azure Portal, PowerShell, CLI or REST API (not managed using TSQL in Azure SQL Database).
Review Azure SQL Database configuration to verify that audit records are produced when privileges/permissions/role memberships are retrieved. To determine if an audit is configured, follow the instructions below: Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an audit to review the retrieval of privilege/permission/role membership information. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script.
Review Azure SQL Database configuration to verify that audit records are produced when the system denies or fails to complete attempts to retrieve privileges/permissions/role membership. To determine if an audit is configured, follow the instructions below: Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script.
When Audits are enabled, they start up when the audits are enabled and remain operating until the audit is disabled. Check if an audit is configured and enabled. To determine if session auditing is configured and enabled, follow the instructions below: Run this TSQL command to determine if SQL Auditing is configured and enabled: SELECT * FROM sys.database_audit_specifications where (name = 'SqlDbAuditing_ServerAuditSpec' or name = 'SqlDbAuditing_AuditSpec') and is_state_enabled = 1 All currently defined audits for the Azure SQL Database instance will be listed. If no audits are returned, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
If an Azure SQL Database Audit is not in use for audit purposes, this is a finding, unless a third-party product is being used that can perform detailed auditing for Azure SQL Database. Review system documentation to determine whether Azure SQL Database is required to audit any events and fields in addition to those in the standard audit. If there are none specified, this is not a finding. If Azure SQL Database Audit is in use, compare the audit specification(s) with the documented requirements. If any such requirement is not satisfied by the audit specification(s) (or by supplemental, locally-deployed mechanisms), this is a finding.
Design and deploy an audit that captures all auditable events and data items. In the event a third-party tool is used for auditing, it must contain all the required information, including but not limited to, events, type, location, subject, date and time, and who made the change. Implement additional custom audits to capture the additional organizational required information.
To obtain the Azure SQL Database audit file location(s), navigate to the Azure Portal, select the Azure SQL Database, then select "Auditing". Review the storage settings for the audit. Verify that the audit storage has the correct permissions by doing the following: 1. Review the Azure roles and users by navigating to the Azure Portal. 2. Review the Azure Server controlling the Azure SQL Database. 3. Select "Access Control (IAM)". 4. Select "Role assignments" and review the roles assigned to each user. 5. Select "Roles" and then select "View" under the "Details" column for each role. Any roles or users with Read permissions to the auditing policy must be documented. If not documented, this is a finding.
Modify audit permissions to meet the requirement to protect against unauthorized access. To review the Azure roles and users, navigate to the Azure Portal and review the Azure Server controlling the Azure SQL Database. 1. Select "Access Control (IAM)". 2. Select "Role assignments" and review the roles assigned to each user. 3. Select "Roles", and then select "View" under the Details column for each role. 4. Remove any undocumented permissions or excessive read permissions to audit storage for user and roles.
Obtain the Azure SQL Database audit file location(s) by navigating to the Azure Portal and selecting the Azure SQL Database, then selecting Auditing. Review the storage settings for the audit. Verify that the audit storage has the correct permissions by doing the following: 1. Navigate to the Azure Portal to review the Azure roles and users. 2. Review the Azure Server controlling the Azure SQL Database. 3. Select "Access Control (IAM)". 4. Select "Role assignments" and review the roles assigned to each user. 5. Select "Roles", and then select "View" under the Details column for each role. Any roles or users with Write permissions to the auditing policy must be documented. If not, this is a finding.
Modify audit permissions to meet the requirement to protect against unauthorized modification. It is recommended to use immutable storage to prevent altering audits once created. https://docs.microsoft.com/en-us/azure/storage/blobs/immutable-storage-overview To review the Azure roles and users, navigate to the Azure Portal, and review the Azure Server controlling the Azure SQL Database. 1. Select "Access Control (IAM)". 2. Select "Role assignments" and review the roles assigned to each user. 3. Select "Roles", and then select "View" under the Details column for each role. 4. Remove any undocumented permissions or excessive write permissions to audit storage for user and roles.
Obtain the Azure SQL Database audit file location(s) by navigating to the Azure Portal and selecting the Azure SQL Database, then selecting Auditing. Review the storage settings for the audit. Verify that the audit storage has the correct permissions by doing the following: 1. Navigate to the Azure Portal to review the Azure roles and users. 2. Review the Azure Server controlling the Azure SQL Database. 3. Select "Access Control (IAM)". 4. Select "Role assignments" and review the roles assigned to each user. 5. Select "Roles", and then select "View" under the Details column for each role. Any roles or users with Write permissions to the auditing policy must be documented. If not, this is a finding.
Modify audit permissions to meet the requirement to protect against unauthorized access. To review the Azure roles and users, navigate to the Azure Portal, and review the Azure Server controlling the Azure SQL Database. 1. Select "Access Control (IAM)". 2. Select "Role assignments" and review the roles assigned to each user. 3. Select "Roles", and then select "View" under the Details column for each role. 4. Remove any undocumented permissions or excessive read permissions to audit storage for user and roles.
Review vendor documentation and vendor websites to identify vendor-provided demonstration or sample databases, database applications, objects, and files. Review the Azure SQL Database to determine if any of the demonstration and sample databases, database applications, or files are installed in the database or are included with the Azure SQL Database. If any are present in the database or are included with the Azure SQL Database, this is a finding.
Remove any demonstration and sample databases, database applications, objects, and files from the Azure SQL Database. Drop Database Syntax: https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-transact-sql?view=azuresqldb-current
Azure SQL Database must only use approved firewall settings, including disabling public network access. This value is allowed by default in Azure SQL Database and must be disabled if not otherwise documented and approved. Obtain a list of all approved firewall settings from the database documentation. From the Azure Portal Dashboard, click the database, then click "Set Server Firewall". Verify that the public network access option is set to disabled. If the value is enabled and not specifically approved in the database documentation, this is a finding.
Assign the approved policy to Azure SQL Database. 1. From the Azure Portal Dashboard, click the "database". 2. Click "Set Server Firewall". 3. Review the public network access option. 4. Check the box to "Disable" public network access. 5. Click "Save". For more information about connection policies: https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-architecture
Review Azure SQL Database users to determine whether shared accounts exist. (This does not include the case where Azure SQL Database has a guest or public account that is providing access to publicly available information.) If accounts are determined to be shared, determine if individuals are first individually authenticated. Where an application connects to Azure SQL Database using a standard, shared account, ensure it also captures the individual user identification and passes it to Azure SQL Database. If individuals are not individually authenticated before using the shared account (e.g., by the operating system or possibly by an application making calls to the database), this is a finding. If accounts are determined to be shared, determine if they are directly accessible to end users. If so, this is a finding.
Remove user-accessible shared accounts and use individual user IDs. If necessary, use the DROP USER command to remove user-accessible shared accounts. Example provided below. DROP USER SharedAccount; https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-user-transact-sql
To verify that Azure Active Directory is configured as the authentication type, use the following PowerShell commands: $LogicalServerName = "myServer" Get-AzSqlServer -ServerName $LogicalServerName | Get-AzSqlServerActiveDirectoryOnlyAuthentication If AzureADOnlyAuthentication returns False, this is a finding.
To set the Azure Active Directory Administrator, use the following PowerShell command: $LogicalServerName = "myServer" Set-AzSqlServerActiveDirectoryAdministrator -ResourceGroupName "myResourceGroup" -ServerName $LogicalServerName -DisplayName "myAADIdentify" Azure Active Directory Authentication can be enabled using either PowerShell or the Azure CLI. To enable Azure Active Directory Authentication using PowerShell, use the commands below: ###### ###### Sets the AAD Admin in the SQL Server using PowerShell ###### ###### $LogicalServerName = "myServer" $ResourceGroup = "myResourceGroup" $DisplayName = "<AAD Principal>" $ObjectId = "<GUID for AAD Principal>" Set-AzSqlServerActiveDirectoryAdministrator ` -ResourceGroupName $ResourceGroup ` -ServerName $LogicalServerName ` -DisplayName $DisplayName ` -ObjectId$ObjectId #Sets AD Admin Only Get-AzSqlServer -ServerName $LogicalServerName ` | Enable-AzSqlServerActiveDirectoryOnlyAuthentication To enable Azure Active Directory Authentication using the Azure CLI, use the commands below: ###### ###### Sets the AAD Admin in the SQL Server using the Azure CLI ###### ###### az sql server ad-admin create ` --resource-group $ResourceGroup --server $LogicalServerName ` --display-name $DisplayName ` --object-id $ObjectId ` #Sets AD Admin Only az sql server ad-only-auth enable ` --resource-group $ResourceGroup ` --name $LogicalServerName https://docs.microsoft.com/en-us/cli/azure/sql/server/ad-only-auth?view=azure-cli-latest https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure?tabs=azure-powershell
Review documentation, Azure SQL Database settings, and authentication system settings to determine if nonorganizational users are individually identified and authenticated when logging onto the system. If accounts are determined to be shared, determine if individuals are first individually authenticated. Where an application connects to Azure SQL Database using a standard, shared account, ensure that it also captures the individual user identification and passes it to Azure SQL Database. If the documentation indicates that this is a public-facing, read-only (from the point of view of public users) database that does not require individual authentication, this is not a finding. If nonorganizational users are not uniquely identified and authenticated, this is a finding.
Ensure all logins are uniquely identifiable and authenticate all nonorganizational users who log onto the system. This likely would be done via a combination of Azure Active Directory with unique accounts and the Azure SQL Database by ensuring mapping to individual accounts. Verify server documentation to ensure accounts are documented and unique.
To validate Azure role-based access controls (RBAC) for a specific resource, use the PowerShell script below: $LogicalServerName = "myServer" $ResourceScope = Get-AzResource -name $LogicalServerName | Where-Object {$_.ResourceType -eq "Microsoft.Sql/servers"} | Select-Object -ExpandProperty ResourceID Get-AzRoleAssignment | Where-Object {$_.Scope -eq $ResourceScope} If a user not assigned information system management responsibilities has membership in any of the following roles, this is a finding: ##SQL DB Contributor ##SQL Security Manager ##SQL Server Contributor ##User Access Administrator ##Owner ##Contributor ##Reader
To remove an Azure RBAC role assignment, use Remove-AzRoleAssignment PowerShell command. Example: Remove-AzRoleAssignment ` -SignInName "myAADIdenity" ` -ResourceGroupName "myResourceGroup" ` -ResourceName "myServerName" ` -ResourceType "Microsoft.Sql/servers" ` -RoleDefinitionName "myRole" `
Run the PowerShell command below to determine database encryption status: $LogicalServerName = "myServerName" $RGname = "myRG" $DBName = "myDatabaseName" Get-AzSqlDatabaseTransparentDataEncryption -ServerName $LogicalServerName -ResourceGroupName $RGname -DatabaseName $Dbname If the application owner and Authorizing Official have determined that encryption of data at rest is required and the "EncryptionState" column returns "UNENCRYPTED" or "DECRYPTION_IN_PROGRESS", this is a finding.
If Azure SQL Database Transparent Data Encryption is disabled, use the Set-AzSqlDatabaseTransparentDataEncryption command to enable. $LogicalServerName = "myServerName" $RGname = "myRG" $DBName = "myDatabaseName" $TDEstate = "Enabled" Set-AzSqlDatabaseTransparentDataEncryption -ResourceGroupName $RGname -ServerName $LogicalServerName -DatabaseName $DBname -State $TDEstate
Review system documentation to obtain the organization's definition of circumstances requiring automatic session termination. If the documentation explicitly states that such termination is not required or is prohibited, this is not a finding. If the system owner, data owner, or organization requires additional assurance, this is a finding.
Determine the situations when a user-initiated database session must be terminated. Note: The user running the commands shown below requires the KILL DATABASE CONNECTION permission. The server-level principal login has the KILL DATABASE CONNECTION. In the SQL Server Management Studio ,as an authenticated user connected to master database, run the following command to list all user sessions: SELECT c.session_id,host_name,program_name,nt_domain, login_name, connect_time, last_request_end_time FROM sys.dm_exec_sessions AS s JOIN sys.dm_exec_connections AS c ON s.session_id= c.session_id; https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-sessions-transact-sql?view=azuresqldb-current Example output: 76 MyComputer Microsoft SQL Server Management Studio - Transact-SQL IntelliSense NULL MyLogin 2022-08-26 20:08:38.170 2022-08-26 20:22:39.697 From the output identify the names of users whose session_ids should be terminated. Using the user for each session to be terminated, run the following command (still in SQL Server Management Studio). Example to terminate user "MyLogin" sessions from example output: KILL <SPID> - where <SPID> is the Session_ID of the session you want to terminate. Reference: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/kill-transact-sql?view=azuresqldb-current
Review Azure SQL Database securables and built-in role membership to ensure only authorized users have privileged access and the ability to create server-level objects and grant permissions to themselves or others. Review the system documentation to determine the required levels of protection for Azure SQL Database securables. Review the permissions in place in the control and data planes in Azure SQL Database. If the actual permissions do not match the documented requirements, this is a finding. Ensure only the documented and approved logins have privileged functions in Azure SQL Database. If the current configuration does not match the documented baseline, this is a finding.
Restrict permissions to Azure SQL Database securables to only authorized users.
Review the system documentation for a description of how audit records are offloaded and how local audit log space is managed. From the Azure Portal Azure SQL Database page, select Auditing. Review the audit storage methods in use. If Azure SQL Database audit records are not written directly to or systematically transferred to a centralized log management system, this is a finding.
Configure Azure SQL Database audit records to be written directly to a centralized audit storage location. https://docs.microsoft.com/en-us/azure/azure-sql/database/auditing-overview#audit-storage-destination To configure writing audit logs to a storage account, select "Storage" in the "Auditing" section. Select the Azure storage account where logs will be saved, and then open Advanced properties to select the retention period. Click "Save". Logs older than the retention period are deleted.
Refer to the online documentation for the Azure SQL Database Audit configuration or the online documentation for the PowerShell cmdlet Get-AzSQLServerAudit using the links provided below. https://docs.microsoft.com/en-us/azure/azure-sql/database/auditing-overview#manage-auditing https://docs.microsoft.com/en-us/powershell/module/az.sql/get-azsqlserveraudit?view=azps-6.4.0 Use the following PowerShell script to check for the proper configuration settings: $FormatEnumerationLimit=-1 Get-AzSqlServerAudit -ResourceGroupName "Resource Group Name" -ServerName "Azure SQL Server Name" | Format-List -Property ServerName, *TargetState If the BlobStorageTargetState, EventHubTargetState, or LogAnalyticsTargetState is disabled, this is a finding.
Review the Azure SQL Database Audit file configuration information. https://docs.microsoft.com/en-us/azure/azure-sql/database/auditing-overview#manage-auditing There are multiple options for configuring where audit logs will be written. Logs can be written to an Azure Blob Storage with Azure storage account, to a Log Analytics workspace, or to Event Hub. Any combination of these options can be configured, and audit logs will be written to each. When writing logs to an Azure Storage account, the default value for retention period is "0" (unlimited retention).
Azure SQL Database must provide notice upon audit storage reaching capacity. Verify if an Azure Rule exists with the following command example: $storageAcct = Get-AzStorageAccount -ResourceGroupName "Name of RG for Audit Storage" -Name "Audit Storage Account Name" $metric = Get-AzMetricAlertRuleV2 | Where-Object TargetResourceId -eq $storageAcct.Id $metric.Criteria If no alert exists, this is a finding. If the criteria does not match 75 percent or less than the maximum capacity of 5 TiB, this is a finding.
Utilize Alerts in Microsoft Azure Monitoring and/or third-party tools to configure the system to notify appropriate support staff immediately upon storage volume utilization reaching 75 percent. https://docs.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-overview
Review Azure SQL Database configuration to verify that audit records are produced when denied actions occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: APPLICATION_ROLE_CHANGE_PASSWORD_GROUP BACKUP_RESTORE_GROUP DATABASE_OBJECT_CHANGE_GROUP DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OPERATION_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_PRINCIPAL_CHANGE_GROUP DATABASE_PRINCIPAL_IMPERSONATION_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP DBCC_GROUP SCHEMA_OBJECT_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Azure SQL Database must only use approved firewall settings, including denying public network access. This value is allowed by default in Azure SQL Database and should be disabled if not otherwise documented and approved. Obtain a list of approved firewall settings from the database documentation. Verify that the public network access option is set to disabled. If the value is enabled and not in use and specifically approved in the database documentation, this is a finding. 1. From the Azure Portal Dashboard, click "Set Server Firewall". 2. Review the Allow Azure services and resources to access this server option.
Assign the approved policy to Azure SQL Database. 1. From the Azure Portal Dashboard, click on the database. 2. Click "Set Server Firewall". 3. Review the public network access option. 4. Check the box to "Disable" public network access. 5. Click "Save". For more information about connection policies: https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-architecture
Azure SQL Database must only use approved firewall settings, including denying access to azure services and resources to the server. This option is denied by default in Azure SQL Database and should be left disabled if not otherwise documented and approved. Obtain a list of approved firewall settings from the database documentation. Verify that the "Allow Azure services and resources to access this server" option is disabled. 1. From the Azure Portal, navigate to the Azure SQL Database Dashboard. 2. Select "Set Server Firewall" on the top menu. 3. Under "Exceptions", review the "Allow Azure services and resources to access this server" option and verify that the value is not checked. If the "Allow Azure services and resources to access this server" option is enabled, it must be necessary and specifically approved in the database documentation, otherwise this is a finding.
Assign the approved policy to Azure SQL Database. 1. From the Azure Portal Dashboard, click "Set Server Firewall". 2. Review the Allow Azure services and resources to access this server option. 3. Uncheck the box to "Deny Azure" services and resources to access this server. 4. Click "Save". For more information about connection policies: https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-architecture
Document transmission protection mechanisms based on organizationally defined requirements, if this documentation does not exist this is a finding. Validate that transmission protection mechanisms match documentation of organizationally defined requirements, if discrepancies exist this is a finding. Run the following PowerShell script to check the TLS version: $ResourceGroupName = '<Resource Group Name>' Get-AzSqlServer -ResourceGroupName $ResourceGroupName | Format-Table ServerName,MinimalTlsVersion Ensure that the minimum TLS version property is set to the latest available TLS version, if a less secure TLS version is set this is a finding.
Implement and document protective measures against unauthorized disclosure and modification during preparation for transmission. https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-settings https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-architecture https://docs.microsoft.com/en-us/azure/azure-sql/database/network-access-controls-overview
Document reception protection mechanisms based on organizationally defined requirements, if this documentation does not exist this is a finding. Validate that reception protection mechanisms match documentation of organizationally defined requirements, if discrepancies exist this is a finding. Run the following PowerShell script to check the TLS version: $ResourceGroupName = '<Resource Group Name>' Get-AzSqlServer -ResourceGroupName $ResourceGroupName | Format-Table ServerName,MinimalTlsVersion Verify that the minimum TLS version property is set to the latest available TLS version. If a less secure TLS version is set, this is a finding.
Implement and document protective measures against unauthorized disclosure and modification during transmission reception. https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-settings https://docs.microsoft.com/en-us/azure/azure-sql/database/connectivity-architecture https://docs.microsoft.com/en-us/azure/azure-sql/database/network-access-controls-overview
Review Azure SQL Database configuration to verify that audit records are produced when security objects are accessed. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an audit to review the retrieval of privilege/permission/role membership information. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script.
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to access security objects occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when categorized information is accessed. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to access categories of information occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when privileges/permissions are added. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to add privileges/permissions occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when privileges/permissions are modified. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to modify privileges/permissions occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when security objects are modified. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to modify security objects occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when categorized information is modified. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to modify categorized information occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when privileges/permissions are deleted. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to delete privileges/permissions occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when security objects are deleted. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to delete security objects occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_CHANGE_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when categorized information is deleted. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful attempts to delete categorized information occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when successful logons or connections occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful logons or connection attempts occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: FAILED_DATABASE_AUTHENTICATION_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced for all privileged activities or other system-level access. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: APPLICATION_ROLE_CHANGE_PASSWORD_GROUP BACKUP_RESTORE_GROUP DATABASE_CHANGE_GROUP DATABASE_OBJECT_CHANGE_GROUP DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OPERATION_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_PRINCIPAL_CHANGE_GROUP DATABASE_PRINCIPAL_IMPERSONATION_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP DBCC_GROUP SCHEMA_OBJECT_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP USER_CHANGE_PASSWORD_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced for all unsuccessful attempts to execute privileged activities or other system-level access. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: APPLICATION_ROLE_CHANGE_PASSWORD_GROUP BACKUP_RESTORE_GROUP DATABASE_CHANGE_GROUP DATABASE_OBJECT_CHANGE_GROUP DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OPERATION_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_PRINCIPAL_CHANGE_GROUP DATABASE_PRINCIPAL_IMPERSONATION_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP DBCC_GROUP SCHEMA_OBJECT_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP USER_CHANGE_PASSWORD_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced showing starting and ending time for user access to the database(s). To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT distinct audit_action_name FROM sys.database_audit_specification_details ORDER BY audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: APPLICATION_ROLE_CHANGE_PASSWORD_GROUP BACKUP_RESTORE_GROUP DATABASE_CHANGE_GROUP DATABASE_OBJECT_CHANGE_GROUP DATABASE_OBJECT_OWNERSHIP_CHANGE_GROUP DATABASE_OBJECT_PERMISSION_CHANGE_GROUP DATABASE_OPERATION_GROUP DATABASE_OWNERSHIP_CHANGE_GROUP DATABASE_PERMISSION_CHANGE_GROUP DATABASE_PRINCIPAL_CHANGE_GROUP DATABASE_PRINCIPAL_IMPERSONATION_GROUP DATABASE_ROLE_MEMBER_CHANGE_GROUP DBCC_GROUP SCHEMA_OBJECT_CHANGE_GROUP SCHEMA_OBJECT_OWNERSHIP_CHANGE_GROUP SCHEMA_OBJECT_PERMISSION_CHANGE_GROUP USER_CHANGE_PASSWORD_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when concurrent logons/connections by the same user from different workstations occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when successful accesses to objects occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced when unsuccessful accesses to objects occur. To determine if an audit is configured, execute the following script. Run this TSQL command to determine if SQL Auditing AuditActionGroups are configured: SELECT DISTINCT sd.audit_action_name FROM sys.database_audit_specification_details sd JOIN sys.database_audit_specifications s ON s.database_specification_id = sd.database_specification_id WHERE (name = 'SqlDbAuditing_ServerAuditSpec' /*Server Audit*/ OR name = 'SqlDbAuditing_AuditSpec') /*Database Audit*/ AND s.is_state_enabled = 1 ORDER BY sd.audit_action_name If no values exist for AuditActionGroup, this is a finding. Verify the following AuditActionGroup(s) are configured: SCHEMA_OBJECT_ACCESS_GROUP If any listed AuditActionGroups do not exist in the configuration, this is a finding.
Deploy an Azure SQL Database audit. Refer to the supplemental file "AzureSQLDatabaseAudit.txt" PowerShell script. Reference: https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit">https://docs.microsoft.com/en-us/powershell/module/az.sql/set-azsqlserveraudit
Review Azure SQL Database configuration to verify that audit records are produced for all direct access to the database(s). To determine if an audit PredicateExpression (filter) exists, execute the following PowerShell script. 1. In the Azure Portal, open a Cloud Shell session. 2. Run this PowerShell command to determine the PredicateExpression: $ResourceGroup = "myResourceGroup" $ServerName = "myServerName" $FormatEnumerationLimit=-1 Get-AzSqlServerAudit -ResourceGroupName $ResourceGroup -ServerName $ServerName If a PredicateExpression is returned, review the associated filters to determine whether administrative activities are being excluded. If any audits are configured to exclude administrative activities, this is a finding.
Check the system documentation for required Azure SQL Database Audits. Remove any Audit filters that exclude or reduce required auditing. Update filters to ensure administrative activity is not excluded.
Review the system documentation for a description of how audit records are stored. 1. Review the Auditing link in the Azure Portal for the SQL Database. Ensure audit logs are written to more than one storage system. If not, navigate to the Storage Container where the audits are stored via the Portal. 2. Select "Containers". 3. Select the ellipsis on the container for the audit storage. 4. Select "Access Policy". Verify that an Immutable Blob Storage policy has been added to the audit container. If Azure audit logs are written to only one storage system or immutable storage is not enabled, this is a finding.
Enable immutable storage so that audit logs cannot be modified or deleted accidently. https://docs.microsoft.com/en-us/azure/storage/blobs/immutable-policy-configure-container-scope?tabs=azure-portal To configure a time-based retention policy on a container with the Azure portal, follow these steps: 1. Navigate to the desired container. 2. Select "More" on the right, then select "Access policy". 3. In the Immutable blob storage section, select "Add policy". 4. In the Policy type field, select "Time-based retention", and specify the retention period in days. 5. To create a policy with container scope, do not check the box for "Enable" version-level immutability. 6. If desired, select "Allow additional protected appends" to enable writes to append blobs that are protected by an immutability policy. PowerShell: Set-AzRmStorageContainerImmutabilityPolicy -ResourceGroupName <resource-group> ` -StorageAccountName <storage-account> ` -ContainerName <container> ` -ImmutabilityPeriod 10 Alternatively, enable at least two types of audit storage for the Azure SQL Database. In the Azure Portal, select "Auditing". Check at least two of the available storage types and select "Save".