■河南 許紅軍
在各種Web應用中,經常會利用郵件發送通知。如果郵件發送功能存在安全問題的話,黑客可能趁機對郵件的內容進行篡改,或者因此導致開放轉發第三方郵件的情況。
和郵件安全相關的問題可能包括郵件頭注入漏洞,使用hidden參數保存收件人信息,以及郵件服務器的開放轉發等。
其中郵件頭注入攻擊是通過在郵件消息中的收件人或標題等字段中插入換行符,來達到添加新的郵件頭字段或非法篡改郵件正文的目的。
例如,正常的郵件發送頁面源代碼中可能包括:“”等行。其中的收件人等信息是硬編碼處理的,郵件內容雖然存在換行但沒有安全問題,問題出在額外的hidden參數,即“From”頭部參數,用來指定發件人信息。用戶提交的發件人信息會被添加到郵件頭部中,但程序并沒有對其進行有效校驗。
正常的郵件發送頁面對于郵件地址輸入框設定的是Text類型,只能輸入一行信息。但是黑客會利用各種方法將其修改為“textarea”類型,可以輸入多行信息。這樣當其點擊發送按鈕后,這些信息就會提交到目標網站中的PHP處理程序中,導致發出被篡改的郵件。
例如,黑客會在郵件正文包含惡意鏈接,通過密送方式發送給其他用戶,讓不知情的用戶誤以為是正常郵件,當點擊其中的惡意鏈接后,就會招致惡意網站的攻擊。
當然,黑客除了添加“Bcc”外,還可添加“Cc”“To”“Replay-To”等頭部參數。甚至可以添加“Subject”標題參數。這樣,就會在郵件頭中存在兩個“Subject”參數,根據用戶所使用的郵件客戶端類型,可以決定究竟顯示哪個郵件主體。除了非法添加郵件頭外,黑客還可能對郵件的正文進行篡改。
此外,黑客還可在郵件中非法添加惡意附件,其中包含了病毒或木馬程序,這是利用了郵件的MIME格式信息,來構造包含惡意信息的郵件。
黑客通過這種方式在郵件頭中非法寫入惡意附件的內容。當黑客冒充合法用戶,對其他用戶發送包含病毒的郵件,并且其正文被精心的篡改過,當用戶接收后就會誤以為這是正常的郵件,當打開附件后,就會遭到惡意程序的襲擾。這種惡意的郵件攻擊具有很好的偽裝性,對用戶的威脅是不可忽視的。
黑客之所以可以對郵件進行惡意修改,主要是未對外部傳入的郵件頭進行過濾。因為郵件的消息格式和HTTP是相似的,消息頭和正文之間用空行分隔。在發送郵件時,開發者經常會使用系統內置的“Sendmail”命令,從郵件的消息頭中獲取發送目標的郵箱地址,多數發送郵件程序庫也是利用該方法處理郵件的。因此,如果黑客可以在外界傳入的參數中插入換行符,就可以添加新的消息頭。
換行符在郵件消息頭中有著重要作用,如果未對換行符進行必要處理,就會產生郵件消息頭注入漏洞。尤其是在CGI程序中發送郵件時,經常采用“Sendmail”命令行的方式,不僅容易引發郵件消息頭漏洞,還可能引發OS命令注入漏洞。
對于此類漏洞的防范,最有效的辦法是使用專用的發送郵件的程序庫,不能使用系統級命令來發送郵件。為了徹底防御郵件頭注入漏洞,還需要在郵件頭中禁止包含外界傳入的參數。如果必須接受外界傳入的參數,那么可以通過校驗禁止傳入的參數中包含換行符。
在上述例子中,在郵件頁面中設置了“From”消息頭,因此將其固定并在正文中顯示用戶的郵箱地址,就可以有效解決上述問題。
例如,將“mb_send_mail("webadmin@xxx.com","郵件標題","郵件主體! ".$body." ","From:" .$from)”“?>”進行修改,使其變成“mb_send_mail("webadmin@xxx.com","郵件標題","郵件主體! ".$body." ","合法用戶郵箱:"."From:","From:hefayonghu@xxx.com")”即可。如果郵箱地址或主題允許包含換行符,那么就可能會被添加新的郵件頭或正文。
因此,必須在發送郵件時對換行符號進行校驗,從根本上避免上述漏洞。例如,在網頁源代碼中輸入以下命令:


對From字段進行校驗,如果發現其中存在換行符,就顯示警告信息。
在一些用來免費發送郵件的表單中,為了便于自定義信息,有時會將郵件的收件人等信息指定為hidden參數。例如,網頁可能包含諸如“”等語句。黑客可以借機將hidden參數中的收件人更改為任意的郵箱地址,就可以利用此類表單來發送垃圾郵件。
所以說,收件人郵箱地址等信息不能保存在hidden參數中,必須將其硬編碼在源代碼,或保存在服務器的文件/數據庫中。郵件服務器的開放轉發指的是如果郵件服務器的設置存在問題,就可能使服務器的角色既不是發件人也不是收件人,而是被用于轉發第三方郵件,黑客很容易將其作為發送垃圾郵件的工具。
在PHP等開發工具中,提供了名為“Eval”的函數,如果使用不當很容易造成外界傳入的腳本被非法執行,這其實就是eval注入攻擊。
該漏洞可能造成網站信息泄露、非法篡改數據、執行惡意操作等危險行為,攻擊者甚至可以借此對其他網站進行攻擊。
防御該漏洞直接的方法是不使用eval函數,可以選擇與其功能相當的其他函數,如果一定要使用該函數,那么就應該避免其參數中包含外界傳入的內容。如果允許外界傳遞參數,必須將其限定為只能包含字母或數字的內容。
eval函數主要的功能就是將字符串反序列化到對象。例如,對于“”語句來說,就可以將數組導出為字符串,之后將該字符串進行Base64編碼,便于在網絡上進行傳輸。之后通過隱含參數的方法將其發送出去,其他網站利用“”等語句對上述編碼內容進行解碼,得到具體的字符串,之后拼接字符串并使用eval函數執行。
從表面看起來似乎沒有問題,但攻擊者可以對POST提交的數據進行惡意修改,在其中添加非法的腳本語句,如果對外界傳入的參數沒有進行過濾和檢驗就發送給eval函數執行的話,就可以執行嵌入在其中的惡意腳本,對服務器的威脅很大。
根據以上分析,可以看到eval函數能執行任意的腳本代碼,造成不可忽視的漏洞。
為了避免由此造成的危害,在開發程序時盡量不要使用該函數,可以使用諸如“implode/explode”“serialize/unserialize”等函數實現與其相當的功能。
例如,implode函數使用的參數為數組,通過在各元素之間插入分割字符,將其轉換為字符循環。explode函數功能與之相反。利用這兩個函數即可實現簡單的反序列化功能。例如,可將上述網頁代碼修改為:

即可將數字轉換為字符串,之后發送給接收方,接收方解碼后利用“explode("",$str)”函數還原為字符串。在使用eval函數的情況下,只要禁止外界為其指定參數,也可以有效防止惡意攻擊。如果使用會話變量來替代隱含參數來傳遞數據,那么攻擊者自然沒有辦法注入腳本。因為在不同的頁面之間使用隱含參數的方式發送數據,可能存在數據被惡意修改。例如,可將上述語句修改為:

這樣,就將傳遞的數據保存到會話變量中。在其他頁面中利用“”等語句,從指定的會話變量中提取數據,就可以保證數據的準確性,外界無法對其進行修改。非法腳本中包含了分號、逗號及引號等特殊字符,如果對傳入的eval的參數進行校驗,只允許包含字母和數字,禁止包含上述特殊字符,也可有效避免惡意腳本注入。例如,將上述代碼修改為:

幾乎任何開發語言都允許從外部文件中讀取腳本源代碼,并嵌入當前的程序中,這樣可以提高開發的效率。
例如,PHP可以使用“require”“reqiure_once”“include”“include_once”等函數,來執行調用操作。但如果外界可以指定include的對象的文件名稱,那么很有可能造成非法的腳本文件被調用,這樣其中包含的惡意程序就可以被服務器執行。
當然,這種文件涉及到位于本地的代碼文件。在有些情況下,黑客還可以進行RFI遠程文件包含攻擊。
為了防御文件包含攻擊,最直接的辦法是避免include的路徑中包含外界傳入的參數,如果一定要傳入參數,就必須限制其只能包含字母和數字。
順便說一下,在老版本的PHP中存在“%00”截斷的問題,對于“$_GET['header']”語句來說,將提交的是內容為“xxx.php%00xx.txt”之類的內容,只要遇到“%00”字符,就將后面的內容截斷。

該漏洞的危害表現在,當上傳時路徑可控并使用00截斷。在文件下載時,00截斷會繞過白名單檢查。對于本地文件包含來說,00截斷會擺脫在程序中添加后綴名的限制。
例如,對于“include($header.'.php')語句來說,會讓添加的“.php”的名稱失效。另外,和文件操作有關的地方都可能使用到00截斷。
新版的PHP已經修復了“%00”截斷的問題。
所以,如果在程序中使用了“include($header.'.php')之類的語句,就可以防范非法提交的數據。但是,對于遠程文件包含來說,攻擊者可以可以構造特殊的鏈接來避開這一限制。
根據以上分析,可以看到如果想防御文件包含攻擊,可以對包含的文件名稱進行限制,使其只能包含字母和數字。例如,將代碼修改為:

就可以對提交的內容進行過濾,如果發現包含了非標準的路徑信息,就會顯示警告信息。
對于遠程文件包含來說,可以執行“vim/etc/php.ini”命令,對PHP配置文件進行編輯,在其中的“allow_url_include=”欄中設置為“off”,之后執行“systemctl restart httpd”命令,來重啟HTTPD服務。這樣,就可以禁用遠程文件包含功能了。
實際上,對于服務器上的本地文件來說,一般都是比較安全的。黑客為了對服務器進行攻擊,可能會采取保存會話信息文件的方式向服務器上傳惡意文件。
當禁用了RFI功能后,黑客如果通過各種方法能夠在Web服務器中的會話變量中寫入數據的話,就有可能發起文件包含攻擊。因為對于會話管理來說,當用戶連接到Web服務器后,就會產生對應的Session ID,會話變量等信息。
PHP默認會保存這些會話信息,并會將其保存到本地的一個文件中。如果黑客在會話變量中寫入一些惡意腳本信息,并通過PHP使其保存到某個文件中。并且,如果黑客了解該文件的具體路徑時,就可以通過Include腳本來讀取該文件,然后讓Web服務器來執行這些惡意腳本。
有些網站提供了文件上傳功能,或者允許將會話變量保存到到有特定的文件中,就很容易招致上述惡意攻擊。
例如,在網頁中包含“”等語句,就可以將用戶輸入的數據保存到會話變量中,然后將其保存到指定的文件中。這樣,在其他的頁面就可讀取該會話變量并來獲取相關的信息。
但是,如果攻擊者在網頁提供的輸入欄中寫入了特殊腳本,當提交后該腳本信息就會通過上述會話變量保存到指定的文件中。因為攻擊者可以很容易知道保存會話變量的文件路徑和名稱信息,之后其就可以利用上面談到本地包含攻擊方式來調用該文件,讓服務器執行包含在該文件中的惡意腳本。
對于這種攻擊,最有效的方法是限制用戶輸入的內容,如果發現其提交了非法內容,就將其攔截。
例如,可以將上述代碼修改為:

對用戶提交的數據進行檢測,只能允許其包含字符和數字,否則就顯示警告信息。
通過以上措施,就能基本對一些隱蔽的網絡攻擊進行阻斷。特別是近期“新冠”疫情的影響下,有些別有用心的網絡犯罪分子利用“新型冠狀病毒”字眼進行惡意郵件攻擊,我們要及時做好防范。