背景介紹:
MOVEit Transfer是一種廣泛使用的 Web 應用程序,最近由于一系列 SQL 注入 (SQLi) 漏洞而受到密切關注。這些漏洞影響已發布的 MOVEit Transfer 的各個版本。利用該漏洞可能會授予對 MOVEit Transfer 數據庫的未經授權的訪問,從而允許攻擊者操縱和泄露敏感信息。
補丁分析:
反編譯了未打補丁和打補丁版本的 DLL 文件,并對反編譯的 C# 代碼進行了 Git diff,可以方便地比較未修補版本和修補版本之間的差別。

可以注意到 UserEngine::UserProcessPassChangeRequest() 函數發生了變化,該函數可以從Humans.aspx和machine.aspx中調用,經過仔細檢查,很明顯,如果可以控制 MyLoginName 變量,則很容易受到 SQL 注入攻擊。

最初,通過請求中的 Arg01 參數注入Payloads,可能會出現 SQL 注入,然而,MOVEit 通過 SILUtility.XHTMLClean() 函數來降低風險,從而有效防止任何成功利用此 SQLi 漏洞的行為。
有了這種理解,研究人員重點轉向尋找一種繞過清理并以未經清理的方式操縱 Arg01 參數的方法,因此了解 MOVEit 軟件如何處理請求非常重要。
對于 human.aspx,參數分配是通過 siGlobs.GetIncomingVariables() 進行的,此函數掃描請求并解析可用參數,包括來自表單帖子、查詢字符串、多部分表單、通過“ep”參數加密的查詢字符串的參數(如果參數先前在會話中設置為變量)。

所有提到的函數調用主要涉及解析提供的參數并通過使用 XHTMLClean() 方法進行清理,然后,清理后的值存儲在 siGlobs 對象中。
此過程的最后一步是嘗試從數據庫檢索會話變量,其背后的邏輯如下:如果通過 cookie (ASP.NET_SessionId) 提供會話,后端系統將檢查之前是否為此會話設置了任何變量,如果此類變量存在,它們將覆蓋當前請求中收到的參數。

隨后的過程涉及確定這些變量在數據庫中的存儲點,在相關功能中, SaveArgumentsToSessionForRedirect() 由于與未經身份驗證的操作相關而脫穎而出。
嘗試1:
經過一些 grep 和閱讀代碼后,研究人員偶然發現了一個引起注意的特定代碼片段,該代碼段從密碼變量中設置了 Arg01 的值,在檢查代碼后,密碼沒有經過清理,這意味著在這種情況下 Arg01 將被分配一個完全未經清理的值。
siGlobs.FromSignon = "1";siGlobs.Transaction = "msgpassword";siGlobs.Arg01 = siGlobs.Password;siGlobs.Arg02 = text3;siGlobs.Password = "";siGlobs.Arg07 = "";siGlobs.SaveArgumentsToSessionForRedirect();
然而,研究人員遇到了一個復雜的情況,此代碼片段還為transaction和 FromSignon 變量賦值,這破壞了預期的代碼流,如果提供的transaction參數被值“msgpassword”覆蓋,它會阻止執行“passchangerequest”,盡管如此,研究人員仍決定驗證此代碼是否確實可以為 Arg01 保存未經處理的值并可能觸發 SQL 注入,特別是當transaction變量不是在數據庫中設置而是通過研究人員的參數值設置時。
為了確認這一點,研究人員設置了 Rider debugger,并手動從會話的數據庫中刪除了transaction變量,并觀察到雖然 Arg01 中現在存在特殊字符,但并未發生對 UserEngine::UserProcessPassChangeRequest() 的函數調用,當從 Arg01 中刪除特殊字符時,函數調用可以正常工作,經過幾個小時的調試和研究后,研究人員意識到這是一個死胡同,需要探索其它替代方法。
嘗試2:
在探索對 UserProcessPassChangeRequest 函數的其它調用時,研究人員在 SILMachine.cs (machine.aspx) 中遇到了對同一函數的另一個調用:

但是,清理過程再次應用于 LoginName 變量...研究人員決定重新訪問 git diff 來尋找其它線索,他們有了一個非常有希望的發現——用戶名的清理不一致,清理后,調用 UrlDecode(),但它應該在清理過程之前發生,這種不一致的順序同樣會影響 LoginName 變量。

這種清理順序的不規則性僅在 GetEncryptedQueryParameters() 函數中觀察到,這為研究人員創造了一條潛在的路徑,可以利用加密參數 ep 在 siGlobs 對象中分配 LoginName 值(URL 解碼),同時傳遞transaction參數(可能通過 POST 參數),因為不允許通過查詢(加密或未加密)參數使用transaction。
POST /machine.aspx?ep={encrypted{Username=sql%27injection}} HTTP/2Host: 192.168.29.73Accept-Language: en-GB,en-US;q=0.9,en;q=0.8Content-Type: application/x-www-form-urlencodedContent-Length: 29
Transaction=passchangerequest
然而這一方案中研究人員意識到 Machine.aspx 頁面不支持加密查詢參數,該功能僅限于 human.aspx。
困境:
此時,研究人員有兩條可能的路徑來探索使用 human.aspx 及其加密參數功能:
1.找到一種方法來設置會話變量,其中包含事務“passchangerequest”并通過加密參數進行未凈化的 LoginName
2.找到一種方法,在不設置transaction的情況下,通過加密參數設置未加密的會話變量LoginName
經過一番研究后,研究人員排除了后一種情況的可能性。
最后嘗試:
設置調試器后,研究人員檢查了 SaveArgumentsToSessionForRedirect() 函數的每次調用,消除了不符合的選項,在此過程中,一個特定的調用引起了研究人員的注意,它深深地隱藏在一系列 if/switch 語句中,在調試器中仔細檢查后,transaction和 LoginName 變量完全按照研究人員的期望設置,然而,在代碼中達到這一點時仍然遇到了困難。
try{ string value3 = siGlobs.MyRequest.Cookies["InitialPage"].Value; siGlobs.objDebug.Log(60, string.Format("{0}: InitialPage cookie found: {1}", "Human_Main", value3)); if (Operators.CompareString(value3, CallingPage, TextCompare: false) == 0) { break; } string text6 = ""; string text7 = value3.ToLower(); if (Regex.IsMatch(text7, "[a-z0-9]+\\\\.aspx")) { if (Operators.CompareString(text7, "certtouser.aspx", TextCompare: false) == 0) { if (!SILUtility.StrToBool(siGlobs.FromCertToUser)) { text6 = MyTarget.Substring(0, MyTarget.LastIndexOf("/") + 1) + value3; } } else { text6 = MyTarget.Substring(0, MyTarget.LastIndexOf("/") + 1) + value3; } if (Operators.CompareString(text6, "", TextCompare: false) != 0) { siGlobs.objDebug.Log(60, string.Format("{0}: Redirecting to {1} due to InitialPage cookie", "Human_Main", value3)); siGlobs.SaveArgumentsToSessionForRedirect(); siGlobs.CleanupVariables(); siGlobs.MyResponse.Redirect(siGlobs.MakeEncryptedURLIfNec(text6)); } }}
此特定調用要求調用頁面以外的值設置 InitialValue cookie,在本例中為 humans.aspx,這正是阻止調用此函數的缺失環節。
發出此請求后,將收到一個會話 ID,最重要的是,該 ID 會將transaction參數設置為“passchangerequest”,并將 LoginName 參數設置為 SQL Payloads,這剛好符合了 SQL 注入漏洞的利用。

現在,剩下的唯一任務是在 machine.aspx 請求中設置會話 cookie 并觀察執行情況,在此階段,研究人員預計會話變量將被成功設置,從而由于注入的 SQL Payloads而導致 SQL 異常錯誤。


利用這一點,可以進一步在數據庫中插入新的活動會話,可以利用 Nuclei 執行這些連續的請求來生成系統管理會話和訪問令牌。

你學會了嗎?如果覺得還不錯的話,歡迎分享給更多感興趣的人~
合天網安實驗室
關鍵基礎設施安全應急響應中心
HACK學習呀
安全圈
CNCERT國家工程研究中心
E安全
系統安全運維
關鍵基礎設施安全應急響應中心
E安全
一顆小胡椒
系統安全運維
RacentYY