MSSQL連線資料庫密碼獲取工具與原文數個錯誤糾正

wyzsk發表於2020-08-19
作者: zcgonvh · 2014/04/25 12:41

原文連結:/tips/?id=1067

在測試時發現了一些問題,於是把解決方案與一些結論共享出來,以供需要。

0x00 原文提供的powershell指令碼出錯的解決方案


原文提供的指令碼直接匯入執行會丟擲“資料無效”的錯誤,測試系統在查詢分析器中獲取到的密文為:

[ 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01, 0x15, 0xD1, 0x11, 0x8C, 0x7A, 0x00, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x2A, 0x0B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x51, 0x00, 0x4C, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x61, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, 0x0F, 0x27, 0xAB, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4C, 0xED, 0x01, 0x57, 0x33, 0x68, 0x06, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xE9, 0x20, 0xD6, 0x91, 0xCD, 0x70, 0xF2, 0xC4, 0x0F, 0xB4, 0x97, 0xF7, 0xBB, 0x7C, 0x68, 0x76, 0x4D, 0x1F, 0x9D, 0x6D, 0xC8, 0x56, 0xBF, 0x04, 0x14, 0x00, 0x00, 0x00, 0xEA, 0x60, 0x44, 0xBC, 0xAC, 0xA3, 0x92, 0x1D, 0x04, 0xCC, 0x5E, 0x6C, 0x47, 0xE5, 0x1B, 0x0D, 0xE1, 0xF9, 0x29, 0xD8]

長度為236位元組。而在powershell中獲取到的密文為:

[ 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01, 0x15, 0xD1, 0x11, 0x8C, 0x7A, 0x00, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x2A, 0x0B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x51, 0x00, 0x4C, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x61, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, 0x0F, 0x27, 0xAB, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4C, 0xED, 0x01, 0x57, 0x33, 0x68, 0x06, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xE9, 0x20, 0xD6, 0x91, 0xCD, 0x70, 0xF2, 0xC4] 

長度為196位元組,少了40位元組。經過多次測試發現問題處於查詢語句中的len函式。

msdn(http://technet.microsoft.com/zh-cn/library/ms190329.aspx)上對len函式的說明是:返回指定字串表示式的字元數,其中不包含尾隨空格。

由於函式返回的是字元數,自然要涉及編碼。老外的作業系統是英文,預設使用IBM437 (OEM United States) 編碼,這個編碼是單位元組字符集(sbcs),0x00-0xff都被認為是一個字元,所以獲取的字元長度與位元組長度相等。而中文作業系統預設使用gb2312編碼,屬於雙位元組字符集(dbcs),大於0x7f的位元組都將與其後的一個位元組合併作為一個字元,於是在處理含有大於0x7f的位元組陣列時,len函式獲取的長度與位元組數並不相等,最終會由於密文不完整而出錯。統計完整密文中大於0x7f的位元組總數並排除連續兩個的情況,正好是40.

解決方案:

將原指令碼第74行、第100行共計三個len函式換為datalength函式(http://technet.microsoft.com/zh-cn/library/ms173486.aspx)。

0x01 原文錯誤的定論與擴充利用


原文中有兩個錯誤的定論,而這兩個定論在某些條件下恰好可以組合成為一個新的獲取途徑。

第一個錯誤的定論是存放熵的登錄檔鍵所屬項許可權,原文:“再次提醒,訪問此表項需要本地系統的管理員許可權。”的說法是完全錯誤的。

可以想象,如果sqlserver以低許可權執行時不能訪問這個登錄檔項,那麼執行sp_addlinkedsrvlogin必然會丟擲錯誤,而實際上無論sqlserver的許可權是什麼,這個鍵總可以被sqlserver所訪問。

在預設情況下,此鍵所在項(HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\[instancename]\Security)有以下四個許可權:

system:完全控制,子項繼承
administrators:完全控制,子項繼承
creator owner:完全控制
SQLServerMSSQLUser$[機器名]$[例項名]:查詢,修改,建立子項,列舉子項,通知,讀取DAC  

前兩個許可權不必解釋,第三個許可權代表所有者,一般為system/administrator

第四項代表sqlserver例項使用者組,每個例項對應一個。在修改sqlserver某個例項的服務登入帳戶時,會自動將這個賬戶加入此組。

所以當某個程式的執行賬戶與sqlserver某例項服務賬戶相同,那麼這個程式可以開啟登錄檔並讀取此例項的Entropy Key。實際上,真正起到驗證作用的實際上只有第四項。

第二個錯誤的定論是DAC連線的條件,原文:“開啟專用管理員連線有兩個條件:一是需要有sqlserver的Sysadmin許可權,二是本地伺服器的管理員許可權。”。

而實際上,開啟DAC連結只需要屬於sysadmin固定伺服器角色成員,DAC是支援遠端連線的。

於是有以下推論:

1.當某個程式的執行賬戶與sqlserver某例項服務賬戶相同,那麼這個程式可以開啟登錄檔並讀取此例項的Entropy Key。  
2.由於例項服務賬戶所在使用者組SQLServerMSSQLUser$[機器名]$[例項名]存在於sqlserver登陸名列表中並屬於sysadmin固定伺服器角色成員,於是這個憑據可用來開啟DAC連結。  
3.由於例項服務賬戶屬於本地組成員,所以可以開啟MachineKey進行加密解密。  
4.連線伺服器密碼解密只依賴於Entropy Key,MachineKey和DAC連結  

最後得出結論:

當某個程式的執行賬戶與sqlserver某例項服務賬戶相同,則此程式可以獲取到此sqlserver例項中所有連結伺服器的密碼。  

在實際利用上,一個典型例子就是iis。眾所周知2003的iis預設應用程式池許可權是Network Service,而一些管理員對sqlserver降權的做法也是將sqlserver例項服務賬戶更改為Network Service。於是在上述情況下,任何asp.net應用程式都可以透過windows驗證方式直接作為sa登陸,同時解密並匯出連結伺服器密碼。對於asp等由於使用了來賓帳戶作為預設憑據,則需要執行額外的程式來獲取。

如圖:當sqlserver例項服務賬戶配置為network service執行時,預設iis應用程式池賬戶network service具有讀取登錄檔的許可權:

2014042501272227571.png

於是可以透過工具直接獲取到連結伺服器密碼:

2014042501284933549.png

有了以上結論與原始的Powershell指令碼,工具也就不難寫了,Powershell指令碼實際上就是.net類庫的呼叫,略作修改即可。

lspwd.exe為一鍵獲取工具,lspwd.js為原始碼,編譯命令列:

jsc /r:system.xml.dll lspwd.js

在asp.net中利用的工具以AspxSpy外掛形式提供,GetMSSQLLinkedServerPasswordPlugin.cs為原始碼,編譯命令列:

csc /t:library GetMSSQLLinkedServerPasswordPlugin.cs

GetMSSQLLinkedServerPasswordPlugin.dllGetMSSQLLinkedServerPasswordPlugin.dll.Deflated分別為未壓縮和壓縮後的外掛。

外掛資訊如下:

TypeName:Zcg.Test.AspxSpyPlugins.GetMSSQLLinkedServerPasswordPlugin
MethodName:Run
HTML Result:true
Params:null

輸出:當前伺服器所有能成功連線的sqlserver例項中所有連結資料庫資訊。

呼叫結果如圖:

2014042501315093112.png

附件:mssql_linkedserver_pwd.7z

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章