มีวิธีที่รวดเร็วในการค้นหาคอลัมน์ทั้งหมดใน SQL Server 2008 R2 ที่เข้ารหัส / มีข้อมูลที่เข้ารหัสหรือไม่


10

มีวิธีที่รวดเร็วในการค้นหาคอลัมน์ทั้งหมดใน SQL Server 2008 R2 ที่เข้ารหัส / มีข้อมูลที่เข้ารหัสหรือไม่

ฉันต้องการลบล้างข้อมูลในคอลัมน์ที่เข้ารหัสทั้งหมดในเซิร์ฟเวอร์การพัฒนา (ตามกฎทางธุรกิจของเรา) ฉันรู้ว่าส่วนใหญ่ของคอลัมน์เพราะเราใช้พวกเขาเป็นประจำ แต่ฉันต้องการที่จะอย่างละเอียดและฉันต้องการที่จะพิสูจน์ว่าฉันได้พบพวกเขาทั้งหมด

ฉันค้นหาเว็บแล้วดูในINFORMATION_SCHEMAและตรวจสอบ DMV ที่ฉันคิดว่าน่าจะมีประโยชน์และยังมีsys.columnsและsys.objects ด้วย - แต่จนถึงตอนนี้ก็ไม่มีโชค


1
เราขี้เกียจที่นี่และมีคอลัมน์จากการคำนวณที่ใช้ autodecryptbyvoodoo หากคุณคล้ายกันคุณสามารถดูคำจำกัดความของคอลัมน์ได้
billinkc

คำตอบ:


10

สมมติว่าคุณกำลังพูดถึงข้อมูลที่เข้ารหัสด้วยคีย์ SQL Server มีวิธีหาคอลัมน์เหล่านี้

Key_name()ฟังก์ชั่นจะกลับมาชื่อของสำคัญที่ใช้สำหรับการเข้ารหัสสำหรับค่าที่เฉพาะและจะกลับ NULL ถ้ามีอะไรที่ไม่เข้ารหัสด้วย "รู้จักกันดี" คีย์ (บุคคลที่ 3 หรือง่ายไม่ได้เข้ารหัส)

ด้วย knowlegde นั้นเราสามารถทดสอบทุกคอลัมน์เพื่อดูว่ามันมีอย่างน้อยหนึ่งแถวซึ่งมีค่า varbinary ที่ส่งคืนชื่อคีย์

ฟังก์ชั่นของ key_name ()

--create a test database
CREATE DATABASE [Test_ENCR]
GO

--change context
USE [Test_ENCR]
GO


--because it's possible to encrypt different rows with different keys I'll create 2 keys for this demo
-- Create a symmetric key
CREATE SYMMETRIC KEY symmetricKey1
   WITH ALGORITHM = AES_128
   ENCRYPTION BY PASSWORD = 'password01!';
GO

-- Create a second key
CREATE SYMMETRIC KEY symmetricKey2 
   WITH ALGORITHM = AES_128
   ENCRYPTION BY PASSWORD = 'password02!';
GO



--create a table that will have a column holding:
--1: encrypted row with key1
--2: encrypted row with key2
--3: a non encrypted just varbinary value

CREATE TABLE encryptedTable
(ID int IDENTITY PRIMARY KEY,
EncryptedCol varbinary(256) NOT NULL);
GO


-- open key1
OPEN SYMMETRIC KEY symmetricKey1 
    DECRYPTION BY PASSWORD = 'password01!';
GO

-- open key2
OPEN SYMMETRIC KEY symmetricKey2 
    DECRYPTION BY PASSWORD = 'password02!';
GO

--insert encrypted data with key1
INSERT INTO encryptedTable(encryptedCol)
VALUES ( ENCRYPTBYKEY (Key_GUID('symmetricKey1'), 'EncryptedText1'));
GO

--insert encrypted data with key2
INSERT INTO encryptedTable(encryptedCol)
VALUES ( ENCRYPTBYKEY (Key_GUID('symmetricKey2'), 'EncryptedText2'));
GO


--insert just varbinary data
INSERT INTO encryptedTable(encryptedCol)
VALUES (CONVERT(varbinary(256),'NotEncryptedTextJustVarBinary'))



--have a look, without the key, all varbinary for you.
SELECT * FROM encryptedTable
GO

ผล:

ป้อนคำอธิบายรูปภาพที่นี่

--Return all key_names
SELECT DISTINCT     key_name(encryptedcol), 
                    EncryptedCol 
FROM encryptedTable;

ผล:

ป้อนคำอธิบายรูปภาพที่นี่

วิธีการนำไปใช้เพื่อค้นหาคอลัมน์ที่เข้ารหัส

--How do we dynamically find all the columns that have at least one row with a encrypted value?

-- first we will find all tables and column with a varbinary datatype
-- then we will test all those columns with a simple select
-- If the key_name() function returns a value, the column and table name are stored together with the keyname

--create a table to hold all varbinary columns and tables
CREATE TABLE #TablesWithVarbinCols (    ID int IDENTITY,
                                TableName nvarchar(128),
                                ColumnName nvarchar(128)
                                );

--create a table to hold the end result
CREATE TABLE #TablesWithEncryption (
                                TableName nvarchar(128),
                                ColumnName nvarchar(128),
                                KeyName varchar(128)
                                );


--find and store all table and column names of user tables containing a varbinary column
INSERT INTO #TablesWithVarbinCols (TableName,ColumnName)
SELECT      o.[name] as TableName,
            c.[name] as ColumnName
FROM        sys.objects o
INNER JOIN  sys.columns c
ON          o.[object_id]=c.[object_id] 
INNER JOIN  sys.types t
ON          c.system_type_id=t.system_type_id
WHERE       o.[type]='U'
AND         t.name=N'varbinary'
AND         c.max_length > -1;


DECLARE @col nvarchar(256)
DECLARE @tab nvarchar(256)
DECLARE @c int = 1
DECLARE @MaxC int
DECLARE @SQL varchar(max)

SELECT @MaxC=MAX(ID)
FROM #TablesWithVarbinCols

--loop the previous result and create a simple select statement with a key_name() is not null where clause. 
--If you have a result, store the details
WHILE @c <= @MaxC
BEGIN
    SELECT  @Tab=TableName,
         @col=ColumnName
    FROM    #TablesWithVarbinCols
    WHERE   ID=@c

    SET @SQL='  INSERT INTO #TablesWithEncryption (TableName, ColumnName, KeyName)
                SELECT DISTINCT '''+@Tab +''',''' +@col +''', key_name('+@Col +') from '+ @tab +' 
                WHERE key_name('+@Col +') is not null;'
    exec (@SQL)

    DELETE
    FROM #TablesWithVarbinCols
    WHERE id=@c;
    SET @c=@c+1
END

--select the result
SELECT * FROM #TablesWithEncryption;

ผล:

ป้อนคำอธิบายรูปภาพที่นี่

--cleanup
DROP TABLE #TablesWithVarbinCols;
DROP TABLE #TablesWithEncryption;

8

ปัญหาของการเข้ารหัสระดับเซลล์คือคอลัมน์นั้นไม่ได้เข้ารหัสจริงๆมันเป็นข้อมูลที่อยู่ในคอลัมน์นั้น คอลัมน์เหล่านั้นเป็นเพียงคอลัมน์ varbinary (เพราะนั่นคือสิ่งที่จำเป็น) และอาจมีข้อมูลที่ชัดเจน มันเป็นการใช้งานENCRYPTBY*และDECRYPTBY*ฟังก์ชั่นที่ทำให้ข้อมูลเข้ารหัสอย่างแท้จริง

คุณสามารถเริ่มต้นด้วยการสอบถามมุมมอง sys.columns สำหรับคอลัมน์ทั้งหมดที่เป็น varbinary:

select
  object_name(a.object_id) [objectname]
  ,a.name [columnname]
  ,a.column_id
from
   sys.columns a
   join sys.types b on (a.system_type_id = b.system_type_id)
where
   b.name = N'varbinary';

มิฉะนั้นคุณจะต้องตรวจสอบรหัสของคุณเพื่อระบุว่าจะใช้ฟังก์ชันการเข้ารหัส / ถอดรหัสลับที่ไหน:

select
   object_name(object_id) [objectname]
   ,definition
from
   sys.sql_modules
where
   definition like N'%ENCRYPT%' 
   OR definition like N'%DECRYPT%';

1

เรียกใช้แบบสอบถามด้านล่างในฐานข้อมูลที่เฉพาะเจาะจง

select 
    t.name as [Table],
    c.name as [Column], 
    c.encryption_type_desc
from   
    sys.all_columns c inner join
    sys.tables t on c.object_id = t.object_id
where  
    c.encryption_type is not null 
order by
    t.name,
    c.name

เปลี่ยนแปลงเล็กน้อยจาก

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/ca9d8360-5d7e-4de1-abe6-ce1afda595a9/how-to-find-which-table-columns-are-encrypted?forum=sqlsecurity


1

คุณสามารถค้นหาคอลัมน์ที่เข้ารหัสด้วย keys \ certificate โดยค้นหาคอลัมน์ varbinary ทั้งหมดและตรวจสอบคีย์การเข้ารหัสด้วยฟังก์ชัน KEY_NAME

อย่างไรก็ตามกระบวนการนี้ค่อนข้างแพงและใช้เวลานาน หากคุณต้องการค้นหาคอลัมน์เหล่านี้เป็นประจำฉันขอแนะนำให้ "ติดแท็ก" คอลัมน์ที่มีคุณสมบัติเพิ่มเติม เราสามารถสร้างโซลูชันของ Edward Dortland และ "แท็ก" คอลัมน์ที่พบกับคุณสมบัติเพิ่มเติมเช่นเข้ารหัส, เข้ารหัสลับ, เข้ารหัสลับและเข้ารหัสลับ

--create a table to hold all varbinary columns and tables
CREATE TABLE #TablesWithVarbinCols (    ID int IDENTITY,
                            SchemaName nvarchar(128),
                            TableName nvarchar(128),
                            ColumnName nvarchar(128)
                            );

--find and store all table and column names of user tables containing a 
varbinary column
INSERT INTO #TablesWithVarbinCols (SchemaName,TableName,ColumnName)
SELECT      s.[name] as SchemaName,
            o.[name] as TableName,
            c.[name] as ColumnName
FROM        sys.objects o
INNER JOIN  sys.schemas s
ON          s.[schema_id] = o.[schema_id]
INNER JOIN  sys.columns c
ON          o.[object_id]=c.[object_id] 
INNER JOIN  sys.types t
ON          c.system_type_id=t.system_type_id
WHERE       o.[type]='U'
AND         t.name=N'varbinary'
AND         c.max_length > -1;

DECLARE @sch nvarchar(128)
DECLARE @col nvarchar(256)
DECLARE @tab nvarchar(256)
DECLARE @key nvarchar(256)
DECLARE @cert nvarchar(256)
DECLARE @c int = 1
DECLARE @MaxC int
DECLARE @SQL nvarchar(max)

SELECT @MaxC=MAX(ID)
FROM #TablesWithVarbinCols

--loop the previous result and create a simple select statement with a 
key_name() is not null where clause. 
--If you have a result, store the details
WHILE @c <= @MaxC
BEGIN
    SET @key = NULL;
    SELECT  @sch=SchemaName,
            @Tab=TableName,
            @col=ColumnName
    FROM    #TablesWithVarbinCols
    WHERE   ID=@c


SET @SQL='SELECT DISTINCT @key= key_name('+@Col +') from '+ @tab +' 
            WHERE key_name('+@Col +') is not null;'


exec sp_executesql @SQL, N'@key nvarchar(256) out', @key out

SELECT @cert =  c.name 
from sys.symmetric_keys sk
join sys.key_encryptions ke
    on
    sk.symmetric_key_id= ke.key_id
join sys.certificates c
    on
    ke.thumbprint=c.thumbprint
where sk.name = @key


IF (@key IS NOT NULL)
BEGIN

    SET @SQL=
    'EXEC sp_addextendedproperty @name = N''encrypted'', @value = N''1'', '+
    '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
    '@level1type = N''Table'', @level1name = '''+@tab+''','+
    '@level2type = N''Column'', @level2name = '''+@col+'''
    '

    EXEC sp_executesql @SQL

    SET @SQL=
    'EXEC sp_addextendedproperty @name = N''encryptkey'', @value = '''+@key+''', '+
    '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
    '@level1type = N''Table'', @level1name = '''+@tab+''','+
    '@level2type = N''Column'', @level2name = '''+@col+'''
    '

    EXEC sp_executesql @SQL

    SET @SQL=
    'EXEC sp_addextendedproperty @name = N''encryptcert'', @value = '''+@cert+''', '+
    '@level0type = N''Schema'', @level0name = '''+@Sch+''', '+
    '@level1type = N''Table'', @level1name = '''+@tab+''','+
    '@level2type = N''Column'', @level2name = '''+@col+'''
    '

    EXEC sp_executesql @SQL

END

DELETE
FROM #TablesWithVarbinCols
WHERE id=@c;
SET @c=@c+1

END

drop table #TablesWithVarbinCols

จากนั้นเราสามารถค้นหาคอลัมน์ที่เข้ารหัสได้อย่างง่ายดายโดยการค้นหาคุณสมบัติเพิ่มเติม

--Adjust WHERE clause depending on what tags you are looking for
SELECT
   SCHEMA_NAME(tbl.schema_id) AS SchemaName,    
   tbl.name AS TableName, 
   clmns.name AS ColumnName,
  p.name AS ExtendedPropertyName,    --remove for programming
   CAST(p.value AS sql_variant) AS ExtendedPropertyValue
FROM
   sys.tables AS tbl
   INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
   INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=clmns.column_id AND p.class=1
WHERE p.name in ('encrypted','encryptkey','encryptcert')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.