文章很多專有名詞,而且老外說話的方式和中國的差別還是太大了點……所以有很多地方翻譯的不是很好,見諒。
從重要系統中獲取明文密碼的過程總是充滿著樂趣。mssql伺服器對本地儲存的密碼是進行了加密操作的,鏈結伺服器的相關憑證也不例外,但與此同時mssql也是有自己的手段可以對相關的密碼憑證進行解密。而你可以直接參考使用本文發布的powershell指令碼對相關的憑證進行解密。以進攻者的角度來看,如果想要解密相關的憑證,我們需要有mssql的sysadmin許可權和本地伺服器系統管理員的許可權。從防禦的層面來看,這篇文章的目的主要是想提醒下相關的管理員,不必要的資料庫鏈結、高許可權資料庫鏈結和使用sql server的身份認證會比使用整合的身份認證產生更多不必要的風險。這篇博文推薦給對資料庫感興趣的黑客及打算深入學習的管理員們。
microsoft sql server允許使用者使用mssql管理其它不同型別的資料庫,一般情況下鏈結伺服器用來管理與本地不同版本的mssql服務。當鏈結建立之後,它們可以被配置為使用安全的上下文和靜態sql server憑據。如果sql server的憑據被新增使用了,相關的使用者名稱和密碼會被加密儲存到相關的表內,而這一加密是可逆的。單向不可逆的hash是不可以用於鏈結伺服器的,因為sql server必須要使用明文的密碼資訊去訪問其它的資料庫。所以,如果密碼資訊是使用了對稱加密而不是單向hash的話,sql server自然會有方法去解密相關的密***。本文主要介紹這一加密、解密的過程及其工具化的實現。
mssql將鏈結伺服器的資訊(包含加密的密碼)儲存在master.sys.syslnklgns表中。我們重點關注的加密密碼是儲存在字段「pwdhash」中的(雖然寫著hash但是他不是乙個普通的hash),下圖是乙個例子:
master.sys.syslnklgns表在正常的資料庫連線情況下是無法訪問的,必須在專用管理員連線(dac)下才可以訪問(更多關於dac的資訊請檢視technet.microsoft.com/en-us/libra…)。開啟專用管理員連線有兩個條件:一是需要有mssql的sysadmin許可權,二是本地伺服器的管理員許可權。
如果本地管理員沒有獲得sysadmin的許可權,你只需要將mssql許可權修改為本地系統賬戶即可。更多資訊請參考www.netspi.com/blog/entryi…
下面介紹一些mssql加密的基本原理。首先我們可以先了解一下服務主金鑰(smk)(更多資訊請參考technet.microsoft.com/en-us/libra…)。根據微軟的描述「服務主金鑰為 sql server 加密層次結構的根。
服務主金鑰是首次需要它來加密其他金鑰時自動生成的」可知smk儲存在master.sys.key_encryptions表中,而他的key_id對應的值是102。smk是使用dpapi來加密的,而這裡他有兩個可用的版本,第一種是使用的localmachine加密,另一種是currentuser的相關上下文(意思是sql server服務執行的賬戶)。這裡我們挑使用localmachine的machinekey來單獨加密的、解密時不依賴於sql server賬戶的格式來討論。下面是乙個例子:
為了增強加密的強度,演算法中會加入熵(密碼學用語,可自行查閱),不過演算法中使用到的熵位元組我們可以從登錄檔hklm:\software\microsoft\microsoft sql server\[instancename]\security\entropy
中找到。再次提醒,訪問此表項需要本地系統的管理員許可權。下圖是熵的乙個例子:
搞定上面這些之後(同時必須去除填充位元組等)我們就可以使用dpapi來解密smk了。
從smk的長度(或mssql的版本)我們可以看出兩種不同的加密演算法:mssql 2012使用的是aes,而早期的版本使用的是3des。另外,pwdhash必須解析為bit才可以找到相關的加密密碼。版本使用的演算法參考了高階t-sql程式設計師發布的文章,見stackoverflow.com/questions/2…
即使資料的格式和文章內給出的不太一致,但是也並不難發現正確的加密資料。到此,我們已經有辦法使用smk解密出所有的明***了(當使用的是sql server賬戶而不是windows身份認證)。
該指令碼必須在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明文去解密鏈結伺服器的憑證
複製**
在測試這個的過程中很多問題的產生,要不是dac登入不上,就是powershell的指令碼一直有問題。
目前測試了兩個環境:
1. win2003 + mssql2005
2. win2008 + mssql2008
複製**
除了指令碼有問題,其它都是可以獲取到的。指令碼大部分語法是類似.net的,基本都是在呼叫.net的庫,由於一些時間問題,我就不再獻醜去改了等大牛們來乙個「一鍵獲取」。
先看點2003的測試圖:
1.pwdhash
2.讀取加密的smk
3.檢視登錄檔key
但是在執行指令碼的時候(注意要2.0以上)還是報錯了:
已經測試過兩個引數都非空,而且應該是正確的。
在2008下也是類似的情況。時間關係不再深入,等有興趣的牛牛們再搞搞。
另外,這也是一種「找資料庫連線資訊」的方法。雖然有點奇葩,但是預計還是可行的,以後如果可以安排得過來,而且沒有大牛修改上面的指令碼的話……我再來獻醜。
第一次搞翻譯,翻譯的不好大家多多原諒。
MSSQL資料庫備份之設定密碼
備份 這兩條語句一起才算是完整的備份,第一條是備份資料庫,第二條是備份日誌,在實際使用中推薦使用這種方式 backup database powercheck to disk d back 20070908.bak with password 123456 這是密碼 backup log power...
建立資料庫伺服器遠端鏈結(MSSQL)
建立鏈結伺服器 exec sp addlinkedserver server pp client 鏈結伺服器名 srvproduct provider n sqloledb datasrc n 117.135.132.71 遠端伺服器名稱 catalog n uims go 建立遠端登入 exec ...
加 解密資料庫使用者 密碼的類設計
可以用來加 解密資料庫使用者 密碼等 using system using system.io using system.text using system.security.cryptography namespace mon static protected byte byteiv static...