下面這段代碼是一個WEB系統(tǒng)中顯示廣告內(nèi)容的程序,這個程序從發(fā)現(xiàn)漏洞到現(xiàn)在,歷經(jīng)多次修改,但是每次修改都有安全問題或隱患,這些問題雖然不會直接導致入侵,但是在其他非托管系統(tǒng)中或在使用其他非托管語言開發(fā)的組件中,則會引起更大的安全問題。
<% Response.WriteFile(AdvFile); %> AdvFile = Request.QueryString["Path"]; AdvFile = @"../xdd/" + AdvFile; |
代碼 1
代碼的目的是從用戶端獲取Path 參數(shù)并拼接上文件目錄,然后讀出文件并返回到客戶端。開發(fā)人員認為PATH是A-Z這樣的文件名,實際上攻擊者可以輸入”..”、”\”等特殊符,從而打破目錄限制,訪問當前WEB站點中的任何文件,如Path=../Web.Config,獲取WEB應用程序的配置文件,Path=..\Bin\APP.DLL獲取DLL文件,Path=..\Cert\App.Cert獲取證書文件,通過這樣一個漏洞,應用程序?qū)粽叨?,就成?ldquo;開放式系統(tǒng)”,給攻擊者實施后續(xù)攻擊提供了有力幫助。
開發(fā)人員為了防止攻擊者通過以上方式非法訪問機密文件,采用了下面的保護措施:
AdvFile = AdvFile.ToLower().Replace(".html", "") + ".html"; |
代碼 2
通過強制在文件名后面加上.Html來達到限制只能訪問HTML文件,從而保護其他類型的文件不被非法訪問。這點在C#這樣的托管代碼中,確實可以達到限定訪問文件類型的目的,當然,文件目錄仍然不受限制,攻擊者仍然可以使用..來訪問其他非授權(quán)目錄。但是,這種方式僅僅在托管代碼內(nèi)有效,如果是文件名傳送到非托管代碼,如VB開發(fā)的COM組件,則仍有安全風險。
以下VB代碼是從參數(shù)FileName所指定的文件中獲取內(nèi)容并返回。
Public Function ReadFile(FileName As String) As String Dim FileContent As String Open FileName For Input As #1 Input #1, FileContent Close #1 ReadFile = FileContent End Function |
代碼 3
這段C#代碼調(diào)用VB設置的COM組件讀文件并返回客戶端,在非托管語言中\0是字符串結(jié)束符,如果攻擊者輸入的字符串內(nèi)含有\0這樣的字符,參數(shù)傳入VB開發(fā)的COM組件內(nèi),則系統(tǒng)會丟失在C#程序中加入的.Html。最后文件名會完全受到攻擊者控制,這樣就可以訪問任何文件。
SecurityDemo.FileOperClass oFile = new SecurityDemo.FileOperClass(); AdvFile = AdvFile.ToLower().Replace(".html", "") + ".html"; Response.Write(oFile.ReadFile(ref AdvFile)); |
代碼 4
如攻擊者輸入Path=C:\test.txt%00%00,在C#中字符串是C:\test.txt\0\0.html,但是在VB里面所訪問的文件已經(jīng)變成了C:\test.txt.
在JAVA和PHP等語言中,也存在類似的情況。所以采用拼接的方式在C#中不會有直接的問題,但是如果這種編程方式在其他情形下,就可能會有安全問題。
開發(fā)人員后來又把上述代碼改進行以下改進:
AdvFile = Request.QueryString["Path"]; Regex FileName = new Regex(@"^([A-Za-z](\w+.)+)\.htm|htm|html$"); if (FileName.IsMatch(AdvFile) == false) { AdvFile = "DefaultAdv.htm"; return; } AdvFile = @"../xdd/" + AdvFile; |
代碼 5
這段代碼采用正則表達式來限制用戶的輸入,本意是要求輸入的文件名必須是以.Html或.htm結(jié)尾,但是正則表達式?jīng)]有寫正確!這段正則表達式的限制是文件名必須以Html結(jié)尾或文件名中包含“htm”。
因此,這段代碼又形成了一個可利用的漏洞,攻擊者只需要輸入Path=C:\a.html\..\test.txt就會即滿足正則表達式,又能達到非法訪問的目的。同時,即便上面的正則表達式是正確的,由于攻擊者可以使用%00來突破文件擴展名限制,所以,這種方式也是有安全隱患的。
實際上我們只需要簡單使用C#的FileInfo類來獲取文件真實的文件名以及擴展名并判定是否和我們許可的文件類型相同即可:
AdvFile = Request.QueryString["Path"]; AdvFile = Request.MapPath(".") + AdvFile; try { System.IO.FileInfo oFileInfo = new System.IO.FileInfo(AdvFile); if (oFileInfo.Extension.ToLower() != ".html" || oFileInfo.DirectoryName.ToLower() != "MyDirectory" || !System.IO.File.Exists(AdvFile)) { AdvFile = "DefaultAdv.htm"; return; } AdvFile = oFileInfo.FullName; return; } catch { AdvFile = "DefaultAdv.htm"; return; } |
代碼 6
如對本文有疑問,請?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會為你解答??! 點擊進入論壇