作者:
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具有讀取登錄檔的許可權:
於是可以透過工具直接獲取到連結伺服器密碼:
有了以上結論與原始的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.dll
和GetMSSQLLinkedServerPasswordPlugin.dll.Deflated
分別為未壓縮和壓縮後的外掛。
外掛資訊如下:
TypeName:Zcg.Test.AspxSpyPlugins.GetMSSQLLinkedServerPasswordPlugin
MethodName:Run
HTML Result:true
Params:null
輸出:當前伺服器所有能成功連線的sqlserver例項中所有連結資料庫資訊。
呼叫結果如圖:
附件:mssql_linkedserver_pwd.7z
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!