در این مقاله قصد داریم با نحوه ذخیره کلمات عبور در SQL Server و نحوه کار با آنها آشنا شویم.
به عنوان توسعه دهنده / مدیر، احتمالا از طریق لاگین ویندوزی به SQL Server دسترسی پیدا میکنید. با این حال طریق گزینهی دیگری به صورت
تغییر در Instance SQL به حالت مخلوط (Mixed mode)، و از طریق SQL Login به SQL نیز میتوان به آن دسترسی پیدا کرد. این SQL Logins در دیتابیس Master ساخته میشوند و از طریق
sys.server_principals می توان لیست آنها را مشاهده کرد.
همچنین اطلاعات اضافی در
sys.sql_logins وجود دارند که از
sys.server_principals ارثبری شدهاند. این ۳ ستون اضافه شده،
is_policy_checked ،
is_expiration_checked و
password_hash هستند.
اگر شما با استفاده از تابع
HASHBYTES یک متن مشخص را هش کنید و با کلمه عبوری که در زمان ساخت SQL Login وارد کردهاید مقایسه کنید، خواهید دید که این دو با هم برابر نمیباشند (ستون password_hash در sys.sql_logins). این اختلاف به علت اطلاعات اضافی (
salt) است که به کلمه عبور افزوده شدهاست.
(x = Hash(PlainText + Salt به جای استفاده از (x = Hash(PlainText
SELECT HASHBYTES('SHA2_512',CAST(N'VMT' AS VARBINARY(MAX)))
--0x53DB8AFD20AA76B93DB7BBE855950E679288C843A83899ED4E713B829873306495B6025B7B4FBCDC1BA3EE19C7005BE843A30AC51050C9652E5D1E978DBC3A11
SELECT HASHBYTES('SHA2_512',CAST(N'VMT' AS VARBINARY(MAX))+0xBFE14699)
--0xEF934A8668BD52BEC3295C5DBD2E99555CC074AECBDF32A496C39851A35847DDA7270486B3EC3C77B99334693ECE598617F232C5DC3FCD67EC7D734196913A05
این کار به امنیت بیشتر کمک میکند؛ اگرچه SQL Server اطلاعات Salt را به عنوان بخشی از اطلاعات هش نگهداری میکند. اگر به ستون password_hash دقت کنید، Salt را مشاهده خواهید کرد.
0x0200 BFE14699 EF934A8668BD52BEC3295C5DBD2E99555CC074AECBDF32A496C39851A35847DDA7270486B3EC3C77B99334693ECE598617F232C5DC3FCD67EC7D734196913A05
همانطور که مشاهده میکنید 4 بایت (به صورت جدا شده) برابر با Salt استفاده شده در مثال قبل است. قسمت سمت راست Salt، هش کلمه عبور ماست.
حدس کلمه عبور مربوط به SQL Logins
با استفاده از قطعه کد زیر سعی در حدس کلمه عبور SQL Loginهای سیستم خودم را دارم. از نسخه SQL Server 2012 به بعد، الگوریتم هش کلمه عبور از SHA1 به SHA2-512 تغییر کردهاست.
-- جدول کلمات مورد استفاده برای حدس کلمه عبور
DECLARE @WordList TABLE
(
[Plain] NVARCHAR (MAX)
);
-- درج کلمه عبور با تغییر در نام کاربری
INSERT INTO @WordList ( [Plain] )
SELECT [name] FROM [sys].[sql_logins]
UNION
SELECT REPLACE (REPLACE (REPLACE ([name], 'o', '0'), 'i', '1'), 'e', '3')
FROM [sys].[sql_logins]
UNION
SELECT REPLACE (REPLACE (REPLACE ([name], 'o', '0'), 'i', '1'), 'e', '3') + '.'
FROM [sys].[sql_logins]
UNION
SELECT REPLACE (REPLACE (REPLACE ([name], 'o', '0'), 'i', '1'), 'e', '3') + '!'
FROM [sys].[sql_logins];
-- درج کلمات معمول برای کلمه عبور
INSERT INTO @WordList ( [Plain] )
SELECT N''
UNION ALL
SELECT N'password'
UNION ALL
SELECT N'sa'
UNION ALL
SELECT N'dev'
UNION ALL
SELECT N'test'
UNION ALL
SELECT N'server'
UNION ALL
SELECT N'123456'
UNION ALL
SELECT N'654321'
UNION ALL
SELECT N'asd!@#'
UNION ALL
SELECT N'VMT';
-- تشخیص نوع الگوریتم مورد استفاده در هش کردن کلمه عبور
DECLARE @Algorithm VARCHAR (10);
SET @Algorithm = CASE WHEN @@MICROSOFTVERSION / 0x01000000 >= 11
THEN 'SHA2_512'
ELSE 'SHA1'
END;
-- در صورت یافتن کلمه عبور اطلاعات مربوط به آن در این قسمت بدست میآید
SELECT
[name] ,
[password_hash] ,
SUBSTRING ([password_hash], 3, 4) [Salt] ,
SUBSTRING ([password_hash], 7, ( LEN ([password_hash]) - 6 )) [Hash] ,
HASHBYTES (@Algorithm, CAST([w].[Plain] AS VARBINARY (MAX)) + SUBSTRING ([password_hash], 3, 4)) [ComputedHash] ,
[w].[Plain]
FROM [sys].[sql_logins]
INNER JOIN @WordList [w]
ON SUBSTRING ([password_hash], 7, ( LEN ([password_hash]) - 6 )) = HASHBYTES ( @Algorithm , CAST([w].[Plain] AS VARBINARY (MAX)) + SUBSTRING ([password_hash], 3, 4));
-- همه نامهای کاربری و اطلاعات مربوط به آنها را در اینجا بدست میآید
SELECT
[name] ,
[password_hash] ,
SUBSTRING ([password_hash], 3, 4) [Salt] ,
SUBSTRING ([password_hash], 7, ( LEN ([password_hash]) - 6 )) [Hash]
FROM [sys].[sql_logins];
همانطور که مشاهده میکنید کلمه عبور دو تا از SQL Loginها را بدست آوردیم:
با تغییر در دیکشنری کلمات مربوط به کلمه عبور، کارهای بیشتری را میشود انجام داد.
یکی دیگر از روشهای بررسی کلمه عبور استفاده از تابع
PWDCOMPARE است.
SELECT [name],[password_hash]
FROM sys.sql_logins
WHERE PWDCOMPARE(N'VMT',[password_hash]) = 1