■ 河南 郭建偉
編者按: 在很多Web應(yīng)用中,外部可以利用傳參的方式,來(lái)指定服務(wù)器中的文件名,例如在外界傳入?yún)?shù)時(shí)指定一個(gè)模版文件名,通過(guò)讀取模版文件的內(nèi)容,將其內(nèi)容在網(wǎng)頁(yè)中展示等。這不可避免的會(huì)導(dǎo)致出現(xiàn)一些安全隱患,例如黑客可以非法訪問Web服務(wù)器中的文件,來(lái)讀取服務(wù)器中的敏感文件并展示在網(wǎng)頁(yè)中等。黑客甚至還可以執(zhí)行OS命令注入,在服務(wù)器上非法執(zhí)行各種命令等。
當(dāng)在Web應(yīng)用中允許外界以參數(shù)的形式來(lái)指定服務(wù)器上的文件名時(shí),如果沒有對(duì)文件名進(jìn)行充分的校驗(yàn),就可能出現(xiàn)文件被非法瀏覽,甚至被惡意修改和刪除等,這其實(shí)就是大家常說(shuō)的目錄遍歷漏洞。
實(shí)際上,在網(wǎng)上有很多Web服務(wù)器都存在該漏洞,其危害是不可忽視的。該漏洞會(huì)泄露服務(wù)器中的重要信息,黑客利用該漏洞可以對(duì)網(wǎng)頁(yè)進(jìn)行篡改,發(fā)布各種惡意信息,利用非法鏈接將用戶誘至預(yù)設(shè)的惡意網(wǎng)站,對(duì)服務(wù)器配置文件進(jìn)行破壞,導(dǎo)致服務(wù)器運(yùn)行異常。
黑客還可能修改重要的腳本文件,在服務(wù)器上執(zhí)行各種惡意操作??梢哉f(shuō),凡是能夠由外界指定文件名的頁(yè)面,都可能存在該漏洞,其會(huì)對(duì)所有頁(yè)面產(chǎn)生影響。
對(duì)該漏洞進(jìn)行的防范的要點(diǎn)在于對(duì)外界指定的文件名進(jìn)行嚴(yán)格的限制,例如禁止由外界指定文件名,如果必須指定的話,文件名中不能包含目錄名,即只允許外界讀取指定目錄的內(nèi)容,禁止隨意切換目錄,限制文件名中僅包含字母和數(shù)字,這樣外界用戶就無(wú)法切換目錄,因?yàn)槟夸浢仨毎备艿忍厥庾址?/p>
對(duì)該漏洞進(jìn)行防御,最根本的策略是避免由外界指定文件名,例如將文件名固定,將文件名保存在會(huì)話變量中,不直接指定文件名而使用編號(hào)等方法間接指定等。例如,在某網(wǎng)站中存在“”,“
”,“”等語(yǔ)句,來(lái)讀取外部指定的模版文件,按照正常情況,當(dāng)提交了合法的文件名后,就可以從指定的目錄中讀取該文件,將其內(nèi)容顯示在頁(yè)面中。但當(dāng)攻擊者指定文件名,就會(huì)將密碼文件顯示出來(lái),這對(duì)系統(tǒng)安全構(gòu)成了威脅。將上述網(wǎng)頁(yè)代碼修改為“”,“if ($ tmp_no ==1)”,“{$tmpl = "1.html"}”,“else”,“{die(' 只支持文件編號(hào)!')}”等,根據(jù)編號(hào)來(lái)讀取指定的文件,這樣就避免了上述漏洞。如果必須由外界指定文件名,那么文件名中不能包括目錄名(例如“../”等),就可以盡量降低目錄遍歷漏洞產(chǎn)生的風(fēng)險(xiǎn)。表示目錄 的 字 符 包 括“/”,“”?等,根據(jù)系統(tǒng)的不同存在差異。例如將上述程序修改為”等,利用指定函數(shù)來(lái)讀取傳入文件名,對(duì)其分析后得到末尾的文件名。
這樣,即使黑客傳入了非法文件名,其中包含的雜亂信息會(huì)被自動(dòng)過(guò)濾,Web程序只得到末尾的文件名,當(dāng)進(jìn)行讀取時(shí),只能得到錯(cuò)誤信息。對(duì)傳入文件名的內(nèi)容進(jìn)行限制,只允許包含字母和數(shù)字,也可以防御該漏洞。
在有些網(wǎng)站中,因?yàn)檎`操作等原因,在公開目錄中有時(shí)可能存儲(chǔ)著對(duì)外保密的文件。這樣外界用戶只要知道了文件地址,就可以輕松的瀏覽其內(nèi)容。為防止出現(xiàn)上述情況,可以采取盡量不要在公開目錄放置敏感文件,對(duì)文件設(shè)置合適的訪問權(quán)限,或者直接禁用目錄列表功能等方法來(lái)解決該問題。
如果目錄列表功能沒有被禁用,當(dāng)使用URL指定目錄名稱時(shí),網(wǎng)頁(yè)上會(huì)顯示目錄中的所有文件。例如在Web服務(wù)器上執(zhí)行“vim/etc/httpd/conf/httpd.conf”命令,可看到公開目錄信息。在對(duì)應(yīng)的“”等語(yǔ)句中顯示對(duì)應(yīng)公開目錄的屬性信息,其中“xxx”表示目錄名稱,在“Options”欄中應(yīng)該只包含“Includes ExecCGI FollowSymLinks”內(nèi)容,而禁止包含“Indexs”字樣,這樣該公開目錄的列表功能就被禁用了。
此外,對(duì)公開目錄中的敏感文件名要進(jìn)行必要處理,例如禁止包含日期、用戶名或連續(xù)數(shù)值等易于被猜到的內(nèi)容,避免使用諸如“user.dat”、“data.txt”常用文件名等。關(guān)閉錯(cuò)誤信息顯示功能也可在一定程序上避免暴露敏感文件。例如,在PHP配置文件中輸入“display_errors = off”行,關(guān)閉錯(cuò)誤信息顯示功能。
當(dāng)然,最根本的方法還是在設(shè)計(jì)程序時(shí)將重要文件存放到安全目錄,在租用服務(wù)器時(shí)確認(rèn)可以使用非公開目錄等。
在使用PHP等語(yǔ)言開發(fā)Web程序時(shí),在很多情況下需要使用一些系統(tǒng)級(jí)的命令來(lái)實(shí)現(xiàn)某些功能。即通過(guò)Shell執(zhí)行操作系統(tǒng)命令,或者在開發(fā)中用到的某個(gè)方法時(shí),在其內(nèi)部會(huì)利用Shell來(lái)執(zhí)行OS命令等。
在執(zhí)行這類操作時(shí),就可能出現(xiàn)操作系統(tǒng)命令被任意執(zhí)行的問題。例如在網(wǎng)頁(yè)中需要發(fā)送郵件時(shí),會(huì)使用Linux中 的“sendmail”命令來(lái)實(shí)現(xiàn)。
例如,在某網(wǎng)頁(yè)中存在“$mail = $_Post['mail']”、“system("/usr/sbin/sendmail -i 對(duì)OS注入漏洞進(jìn)行分析,可以發(fā)現(xiàn)在相關(guān)程序內(nèi)部調(diào)用OS命令,多數(shù)是通過(guò)Shell來(lái)啟動(dòng)命令的。 Shell是用來(lái)操作OS的命令行界面,例如Windows中的“cmd.exe”,Linux中的“sh”、“bash”、“csh”等。通過(guò)Shell來(lái)啟動(dòng)命令,能夠使得管道命令或者重定向等功能的使用變得更加快捷。但是,Shell提供的遍歷功能有時(shí)卻成為了OS注入的根源。 并且Shell提供了一次啟動(dòng)多個(gè)命令的語(yǔ)法,因此,黑客就可能在參數(shù)中添加非法內(nèi)容,在原來(lái)命令的基礎(chǔ)上讓其他的命令被隨意執(zhí)行,這樣OS命令注入就產(chǎn)生了。 在Shell中提供了在一個(gè)命令行啟動(dòng)多個(gè)程序的方法,其中OS命令注入就是惡意利用了該特性。在Windows中的“cmd.exe”程序可以利用“&”字符來(lái)連續(xù)執(zhí)行多個(gè)命令。此外,還可以 使 用“|”、“&&”、“||”等字符來(lái)執(zhí)行連續(xù)執(zhí)行多個(gè)命令等。 在Shell中擁有特殊意義的上述字符被稱為元字符,將其作為普通字符使用時(shí)需要進(jìn)行轉(zhuǎn)義。如果在指定的OS命令參數(shù)中的字符串中混入了Shell元字符,就會(huì)讓攻擊者非法添加的命令得以順利執(zhí)行。 而若要產(chǎn)生OS注入漏洞,則必須滿足一些條件,例如包括使用了內(nèi)部調(diào)用的Shell的函數(shù)(例如“system”、“open”等),將外界傳入的參數(shù)傳遞給內(nèi)部調(diào)用的Shell的函數(shù),參數(shù)中的Shell的元字符沒有被轉(zhuǎn)義等。 為了防御OS注入漏洞,可以使用各種方法靈活應(yīng)對(duì)。例如選擇不調(diào)用OS命令的實(shí)現(xiàn)方法,即在程序中不通過(guò)Shell來(lái)調(diào)用系統(tǒng)命令。不要將外界輸入的字符串傳遞給命令行參數(shù),使用安全的函數(shù)對(duì)傳遞來(lái)的參數(shù)進(jìn)行轉(zhuǎn)義等。例如對(duì)于上述存在問題的代碼來(lái)說(shuō),可以不使用系統(tǒng)提供的“senmail”命令來(lái)實(shí)現(xiàn),使用PHP提供的“mb_send_mail”函數(shù),也可以實(shí)現(xiàn)郵件發(fā)送功能。 例如將其修改為“”等語(yǔ)句,來(lái)執(zhí)行郵件發(fā)送功能。這樣,就徹底消除了OS注入漏洞的威脅,還消除了調(diào)用OS命令的系統(tǒng)開銷,從多個(gè)方面提高了應(yīng)用的性能。 如果必須通過(guò)Shell調(diào)用OS命令,或者并不了解所使用的函數(shù)內(nèi)部是否使用了Shell的話,那么不將參數(shù)傳遞給命令行,是防御OS命令注入的有效對(duì)策。例如對(duì)于“sendmail”命令來(lái)說(shuō),可以使用“-t”參數(shù),讓收件人地址不在命令行中指定,而是從郵件的消息頭中讀取。這樣就沒有必要將外界輸入的參數(shù)字符串指派給命令行,即消除了OS命令注入漏洞。 例如將上述代碼修改為“ 注意,為了防止郵件頭注入漏洞,這里對(duì)用戶輸入的郵箱地址進(jìn)行了校驗(yàn),禁止其包含非法內(nèi)容。但是,在調(diào)用“sendmal”命令時(shí),沒有任何外界傳入的參數(shù),OS命令注入漏洞自然無(wú)法成立。 當(dāng)然,對(duì)外界傳入的OS命令的參數(shù)進(jìn)行轉(zhuǎn)義處理,也可以有效消除OS命令注入漏洞。例如將上述代碼修改為“$mail= $_Post['mail']”、“system("/usr/sbin/sendmail -i OS注入漏洞產(chǎn)生的根源
防御OS注入的對(duì)策