2008-11-06

初探 pwdencrypt 與 pwdcompare 函數



SQL Server 7 與 2000 版本,有提供 2 個特殊的 undocumented functions:

1. pwdencrypt : 用於單向加密,但不提解密的功能。
2. pwdcompare : 用於比較已加密的資料與未加密的資料之值是否相同。


雖然經過測試,可以應用在 SQL Server 2005 與 SQL Server 2008 上。
但是您要留意這類 undocumented functions 未來可能隨時被取消刪除、也無法確認是否能相容於新版本的 SQL Server。


使用 pwdencrypt 與 pwdcompare 函數的範例碼如下:

-- 建立範例資料表
USE tempdb
GO
CREATE TABLE tbpwd
(eid varchar(50), epwd varbinary(8000))
GO

-- 使用 pwdencrypt 進行資料加密。
/*
語法如下:
pwdencrypt(加密的資料)
*/
-- 使用 pwdencrypt() 函數,回傳已經編碼過的資料
SELECT pwdencrypt('123')

-- 新增資料列,使用 pwdencrypt 進行資料加密。
INSERT tbpwd
VALUES ('A001',pwdencrypt('myPass789'))
GO

-- 直接查詢資料表的內容,資料已經被加密,模糊化。
SELECT eid N'工號', epwd N'密碼'
FROM tbpwd


請參考下圖所示,被加密過的資料:


接下使用 pwdcompare 函數,與被加密的資料進行比對

/*
使用 pwdcompare 函數,與被加密的資料進行比對,若是相同者,將回傳 1,否則回傳 0 。

語法如下:
pwdcompare(密碼,資料行)
*/
-- 輸入正確的密碼,回傳:1
SELECT pwdcompare('myPass789',epwd)
FROM tbpwd

-- 輸入正確的密碼,但是大小寫不正確,一樣可以正確比對,回傳:1
SELECT pwdcompare('mypass123',epwd)
FROM tbpwd

-- 密碼打錯,回傳:0
SELECT pwdcompare('myPass123',epwd)
FROM tbpwd




其實,登入帳戶的密碼也是可以利用 pwdcompare 函數來進行處理,利用 pwdcompare 可以用來比對您的密碼是否太薄弱,輕輕鬆鬆被解,例如:

1. 帳戶與密碼名稱是否相同。
2. 帳戶的密碼是空白的。
3. 帳戶的密碼是 1 個字元。

以下是修改微軟教材 2787A Designing Security for Microsoft® SQL Server™ 2005 內所提供的範例程式:

-- 建立預存程序
USE master
GO
IF OBJECT_ID('dbo.my_AuditPasswords') IS NOT NULL
DROP PROCEDURE dbo.my_AuditPasswords
GO
CREATE PROCEDURE dbo.my_AuditPasswords
AS
SET NOCOUNT ON
DECLARE @lngCounter int
DECLARE @lngCounter1 int
DECLARE @lngLogCount int
DECLARE @strName VARCHAR(256)

--Create table to hold SQL logins
CREATE TABLE #tLogins
(numID INTEGER IDENTITY(1,1) ,strLogin VARCHAR(255) NULL ,
lngPass INTEGER NULL, strNullPass CHAR(1) NULL)

--Insert non ntuser into temp table
INSERT INTO #tLogins (strLogin)

SELECT name FROM master.sys.sql_logins

SET @lngLogCount = @@ROWCOUNT

-- 判斷密碼是 NULL
SET @lngCounter = @lngLogCount

WHILE @lngCounter <> 0
BEGIN
SET @strName = (SELECT strLogin FROM #tLogins WHERE numID = @lngCounter)

UPDATE #tLogins
SET lngPass = (SELECT PWDCOMPARE ('',(SELECT password_hash FROM master.sys.sql_logins WHERE name = @strName))),strNullPass = 'N'
WHERE numID = @lngCounter

SET @lngCounter = @lngCounter - 1
END

SELECT strLogin AS N'Login Name(密碼空白)'
FROM #tLogins WHERE strNullPass = 'N' AND lngPass = 1

-- 判斷密碼與登入帳戶是否一樣
SET @lngCounter = @lngLogCount

WHILE @lngCounter <> 0
BEGIN
SET @strName = (SELECT strLogin FROM #tLogins WHERE numID = @lngCounter)

UPDATE #tLogins
SET lngPass = (SELECT PWDCOMPARE (@strName,(SELECT password_hash FROM master.sys.sql_logins WHERE name = @strName))),strNullPass = 'S'
WHERE numID = @lngCounter
AND lngPass <> 1

SET @lngCounter = @lngCounter - 1
END

SELECT strLogin AS N'Login Name(密碼與登入帳戶一模一樣)'
FROM #tLogins WHERE strNullPass = 'S' AND lngPass = 1

--Reset column for next password text
update #tLogins set lngPass =0

-- 判斷密碼僅有一個字元
SET @lngCounter = @lngLogCount

WHILE @lngCounter <> 0
BEGIN
SET @lngCounter1 = 1
SET @strName = (SELECT strLogin FROM #tLogins WHERE numID = @lngCounter)

WHILE @lngCounter1 < lngpass =" (SELECT" name =" @strName)))" numid =" @lngCounter"> 1

SET @lngCounter1 = @lngCounter1 + 1
END

SET @lngCounter = @lngCounter - 1
END

SELECT strLogin AS N'Login Name(密碼僅有一個字元)'
FROM #tLogins WHERE lngPass = 1
GO



以下是建立數個登入帳戶,來進行測試

-- 以下是建立數個登入帳戶,來進行測試
USE [master]
GO
-- 建立帳戶 S1,密碼空白
CREATE LOGIN [S1] WITH PASSWORD=N'',
DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO

-- 建立帳戶 S2,密碼與帳戶名稱一樣,也是 S2。
CREATE LOGIN [S2] WITH PASSWORD=N'S2',
DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO

-- 建立帳戶 S3,密碼才一個字元
CREATE LOGIN [S3] WITH PASSWORD=N'z',
DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO


執行此預存程序,進行測試,將可以抓有密碼過於薄弱的登入帳戶


-- 執行此預存程序,進行測試,將可以抓有密碼過於薄弱的登入帳戶
EXEC my_AuditPasswords
GO


請參考下圖所示:


雖然經過測試,可以應用在 SQL Server 2005 與 SQL Server 2008 上。 但是您要留意這類 undocumented functions 未來可能隨時被取消刪除、也無法確認是否能相容於新版本的 SQL Server。


參考資料:
Course 2787: Designing Security for Microsoft SQL Server 2005
http://www.microsoft.com/learning/en/us/syllabi/2787afinal.mspx

pwdencrypt and pwdcompare
http://msmvps.com/blogs/gladchenko/archive/2005/04/06/41083.aspx

SQL Server undocumented password hashing builtins: pwdcompare and pwdencrypt
Laurentiu Cristofor's blog @microsoft.com
http://blogs.msdn.com/lcris/archive/2007/10/31/sql-server-undocumented-password-hashing-builtins-pwdcompare-and-pwdencrypt.aspx

All About Passwords
http://www.enterpriseitplanet.com/security/features/article.php/1582981

2 則留言:

  1. 同樣的資料用pwdencrypt加密後,每次結果都不一樣

    回覆刪除
  2. 的確是有這個現象,推想可能有自動加入類似 Salt 等的機制,讓相同的資料經過加密後,模糊化,無法識別,提高安全性。

    回覆刪除