解密MSSQL連結資料庫的密碼

wyzsk發表於2020-08-19
作者: wefgod · 2014/03/14 12:00

0x00 背景


from:https://www.netspi.com/blog/entryid/221/decrypting-mssql-database-link-server-passwords

建議在看之前先了解下什麼是linked server。比如參考微軟的相關學習資料:

http://technet.microsoft.com/zh-cn/library/ms188279.aspx

文章很多專有名詞,而且老外說話的方式和中國的差別還是太大了點……所以有很多地方翻譯的不是很好,見諒。

從重要系統中獲取明文密碼的過程總是充滿著樂趣。MSSQL伺服器對本地儲存的密碼是進行了加密操作的,連結伺服器的相關憑證也不例外,但與此同時MSSQL也是有自己的手段可以對相關的密碼憑證進行解密。而你可以直接參考使用本文釋出的Powershell指令碼對相關的憑證進行解密。以進攻者的角度來看,如果想要解密相關的憑證,我們需要有MSSQL的Sysadmin許可權和本地伺服器系統管理員的許可權。從防禦的層面來看,這篇文章的目的主要是想提醒下相關的管理員,不必要的資料庫連結、高許可權資料庫連結和使用SQL server的身份認證會比使用整合的身份認證產生更多不必要的風險。這篇博文推薦給對資料庫感興趣的駭客及打算深入學習的管理員們。

0x01 連結伺服器


Microsoft SQL Server允許使用者使用MSSQL管理其它不同型別的資料庫,一般情況下連結伺服器用來管理與本地不同版本的MSSQL服務。當連結建立之後,它們可以被配置為使用安全的上下文和靜態sql server憑據。如果sql server的憑據被新增使用了,相關的使用者名稱和密碼會被加密儲存到相關的表內,而這一加密是可逆的。單向不可逆的hash是不可以用於連結伺服器的,因為sql server必須要使用明文的密碼資訊去訪問其它的資料庫。所以,如果密碼資訊是使用了對稱加密而不是單向hash的話,sql server自然會有方法去解密相關的密文憑證。本文主要介紹這一加密、解密的過程及其工具化的實現。

0x02 連結伺服器的密碼儲存方式


MSSQL將連結伺服器的資訊(包含加密的密碼)儲存在master.sys.syslnklgns表中。我們重點關注的加密密碼是儲存在欄位“pwdhash”中的(雖然寫著hash但是他不是一個普通的hash),下圖是一個例子:

2014031313584244331.jpg

master.sys.syslnklgns表在正常的資料庫連線情況下是無法訪問的,必須在專用管理員連線(DAC)下才可以訪問(更多關於DAC的資訊請檢視http://technet.microsoft.com/en-us/library/ms178068%28v=sql.105%29.aspx)。開啟專用管理員連線有兩個條件:一是需要有mssql的Sysadmin許可權,二是本地伺服器的管理員許可權。

如果本地管理員沒有獲得Sysadmin的許可權,你只需要將MSSQL許可權修改為本地系統賬戶即可。更多資訊請參考https://www.netspi.com/blog/entryid/133/sql-server-local-authorization-bypass

0x03 MSSQL加密


下面介紹一些MSSQL加密的基本原理。首先我們可以先了解一下服務主金鑰(SMK)(更多資訊請參考http://technet.microsoft.com/en-us/library/ms189060.aspx)。根據微軟的描述“服務主金鑰為 SQL Server 加密層次結構的根。

服務主金鑰是首次需要它來加密其他金鑰時自動生成的”可知SMK儲存在master.sys.key_encryptions表中,而他的key_id對應的值是102。SMK是使用DPAPI來加密的,而這裡他有兩個可用的版本,第一種是使用的LocalMachine加密,另一種是CurrentUser的相關上下文(意思是SQL Server服務執行的賬戶)。這裡我們挑使用LocalMachine的Machinekey來單獨加密的、解密時不依賴於SQL Server賬戶的格式來討論。下面是一個例子:

2014031313592481620.jpg

為了增強加密的強度,演算法中會加入熵(密碼學用語,可自行查閱),不過演算法中使用到的熵位元組我們可以從登錄檔HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\[instancename]\Security\Entropy中找到。再次提醒,訪問此表項需要本地系統的管理員許可權。下圖是熵的一個例子:

2014031313595995821.jpg

搞定上面這些之後(同時必須去除填充位元組等)我們就可以使用DPAPI來解密SMK了。

0x04 解密連結伺服器的密碼


從SMK的長度(或MSSQL的版本)我們可以看出兩種不同的加密演算法:MSSQL 2012使用的是AES,而早期的版本使用的是3DES。另外,pwdhash必須解析為bit才可以找到相關的加密密碼。版本使用的演算法參考了高階T-SQL程式設計師釋出的文章,見http://stackoverflow.com/questions/2822592/how-to-get-compatibility-between-c-sharp-and-sql2k8-aes-encryption

即使資料的格式和文章內給出的不太一致,但是也並不難發現正確的加密資料。到此,我們已經有辦法使用SMK解密出所有的明文憑證了(當使用的是SQL Server賬戶而不是windows身份認證)。

0x05 使用指令碼解密連結伺服器的密碼


下面給出powershell的自動解密指令碼Get-MSSQLLinkPasswords.psm1的原始碼連結(譯者提示:該指令碼必須在powershell2.0下執行):

https://github.com/NetSPI/Powershell-Modules/blob/master/Get-MSSQLLinkPasswords.psm1

該指令碼必須在MSSQL伺服器本地執行(DPAPI必須可以訪問到local machine key),同時執行該指令碼的使用者必須有資料庫的sysadmin許可權(在DAC下)可以訪問所有的資料庫例項,而且該賬戶也必須擁有系統管理器許可權(用於讀取登錄檔內的熵)。另外,如果啟用了UAC,指令碼必須以管理員身份執行。下面幾個是指令碼執行的關鍵步驟概要:

1. 獲取本伺服器所有MSSQL的例項
2. 為每個例項開啟DAC訪問
3. 獲取每個例項的pwdhash欄位值
4. 從master.sys.key_encryptions表中讀取出所有key_id值為102的行所對應的SMK,並根據thumbprint欄位來判斷其版本
5. 讀取HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\[instancename]\Security\Entropy 中的熵
6. 使用以上資訊解密SMK
7. 程式根據MSSQL的版本和SMK的長度來確定使用AES演算法或3DES演算法
8. 使用SMK明文去解密連結伺服器的憑證
9. 若程式執行成功則會回顯相關的密碼資訊,比如下圖就是一個例子:

2014031314002642166.jpg

0x06 譯者自測


在測試這個的過程中很多問題的產生,要不是DAC登入不上,就是powershell的指令碼一直有問題。

目前測試了兩個環境:

1. win2003 + mssql2005
2. win2008 + mssql2008

除了指令碼有問題,其它都是可以獲取到的。指令碼大部分語法是類似.NET的,基本都是在呼叫.NET的庫,由於一些時間問題,我就不再獻醜去改了等大牛們來一個“一鍵獲取”。

先看點2003的測試圖:

1.pwdhash

2014031314004519325.png

2.讀取加密的SMK

2014031314010729749.png

3.檢視登錄檔key

2014031314012465783.png

但是在執行指令碼的時候(注意要2.0以上)還是報錯了:

2014031314014787183.png

已經測試過兩個引數都非空,而且應該是正確的。

在2008下也是類似的情況。時間關係不再深入,等有興趣的牛牛們再搞搞。

另外,這也是一種“找資料庫連線資訊”的方法。雖然有點奇葩,但是預計還是可行的,以後如果可以安排得過來,而且沒有大牛修改上面的指令碼的話……我再來獻醜。

第一次搞翻譯,翻譯的不好大家多多原諒。

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

相關文章