摘要:在我們向廠商提交漏洞,發(fā)布了相關(guān)的漏洞分析文章后,由于內(nèi)聯(lián)函數(shù)導(dǎo)致的類(lèi)似安全問(wèn)題在其他的應(yīng)用程序中陸續(xù)曝出。淺析的函數(shù)自帶了一個(gè)內(nèi)聯(lián)函數(shù)用于在應(yīng)用程序中發(fā)送電子郵件。
前言
在我們 挖掘PHP應(yīng)用程序漏洞 的過(guò)程中,我們向著名的Webmail服務(wù)提供商 Roundcube 提交了一個(gè)遠(yuǎn)程命令執(zhí)行漏洞( CVE-2016-9920 )。該漏洞允許攻擊者通過(guò)利用Roundcube接口發(fā)送一個(gè)精心構(gòu)造的電子郵件從而在目標(biāo)系統(tǒng)上執(zhí)行任意命令。在我們向廠商提交漏洞,發(fā)布了相關(guān)的漏洞分析文章后,由于PHP內(nèi)聯(lián)函數(shù)mail()導(dǎo)致的類(lèi)似安全問(wèn)題在其他的PHP應(yīng)用程序中陸續(xù)曝出。在這篇文章中,我們將分析一下這些漏洞的共同點(diǎn),那些安全補(bǔ)丁仍然存在問(wèn)題,以及如何安全的使用mail()函數(shù)。
淺析PHP的mail()函數(shù)
PHP自帶了一個(gè)內(nèi)聯(lián)函數(shù)mail()用于在PHP應(yīng)用程序中發(fā)送電子郵件。開(kāi)發(fā)者可以通過(guò)使用以下五個(gè)參數(shù)來(lái)配置郵件發(fā)送。
http://php.net/manual/en/func...
bool mail( string $to, string $subject, string $message [, string $additional_headers [, string $additional_parameters ]]
這個(gè)函數(shù)的前三個(gè)參數(shù)這里就不細(xì)說(shuō)了,因?yàn)檫@些參數(shù)一般情況下不會(huì)受到注入攻擊的影響。但是,值得關(guān)注的一點(diǎn)是,如果$to參數(shù)由用戶(hù)控制控制的話,那么其可以向任意電子郵件地址發(fā)送垃圾郵件。
郵件頭注入
在這篇文章中我們重點(diǎn)分析后兩個(gè)參數(shù)。第四個(gè)參數(shù)$additional_headers的主要功能是規(guī)定額外電子郵件報(bào)頭。比如From、Reply-To、Cc以及Bcc。由于郵件報(bào)頭由CRLF換行符rn分隔。當(dāng)用戶(hù)輸入可以控制第四個(gè)參數(shù),攻擊者可以使用這些字符(rn)來(lái)增加其他的郵件報(bào)頭。這種攻擊方式稱(chēng)為電子郵件頭注入(或短電子郵件注入)。這種攻擊可以通過(guò)向郵件頭注入CC:或BCC:字段造成發(fā)送多封垃圾郵件。值得注意的是,某些郵件程序會(huì)自動(dòng)將n替換為rn。
為什么沒(méi)有正確處理mail()函數(shù)的第5個(gè)參數(shù)會(huì)引發(fā)安全問(wèn)題
為了在PHP中使用mail()函數(shù),必須配置一個(gè)電子郵件程序或服務(wù)器。在php.ini配置文件中可以使用以下兩個(gè)選項(xiàng):
1.配置PHP連接的SMTP服務(wù)器的主機(jī)名和端口
2.配置PHP用作郵件傳輸代理(MTA)的郵件程序文件路徑
當(dāng)PHP配置了第二個(gè)選項(xiàng)時(shí),調(diào)用mail()函數(shù)的將導(dǎo)致執(zhí)行配置的MTA(郵件傳輸代理)程序。盡管PHP內(nèi)部可以調(diào)用escapeshellcmd()函數(shù)防止惡意用戶(hù)注入其他的shell命令,mail()函數(shù)的第5個(gè)參數(shù)$additional_parameters允許向MTA(郵件傳輸代理)中添加新的程序參數(shù)。因此,攻擊者可以在一些MTA中附加程序標(biāo)志,啟用創(chuàng)建一個(gè)用戶(hù)可控內(nèi)容的文件。
漏洞演示代碼
mail("myfriend@example.com", "subject", "message", "", "-f" . $_GET["from"]);
在上述代碼中存在一個(gè)遠(yuǎn)程命令執(zhí)行漏洞,這個(gè)問(wèn)題容易被沒(méi)有安全意識(shí)的開(kāi)發(fā)人員忽略。GET參數(shù)完全由用戶(hù)控制,攻擊者可以利用該處輸入向郵件程序傳遞其他額外的參數(shù)。舉例來(lái)說(shuō),在發(fā)送郵件的過(guò)程中可以使用-O參數(shù)來(lái)配置發(fā)送郵件的選項(xiàng),使用-X參數(shù)可以指定日志文件的位置。
概念性驗(yàn)證(PoC)
example@example.com -OQueueDirectory=/tmp -X/var/www/html/rce.php
這個(gè)PoC的功能是在Web目錄中生成一個(gè)PHP webshell。該文件(rce.php)包含受到PHP代碼污染的日志信息。因此,當(dāng)訪問(wèn)rce.php文件時(shí),攻擊者能夠在Web服務(wù)器上執(zhí)行任意PHP代碼。讀者可以在 我們的發(fā)布的文章 和 這里 找到更多關(guān)于如何利用這個(gè)漏洞的相關(guān)信息。
最新相關(guān)的安全漏洞
在許多現(xiàn)實(shí)世界的應(yīng)用程序中,有很多由于mail()函數(shù)的第五個(gè)參數(shù)使用不當(dāng)引發(fā)的安全問(wèn)題。最近發(fā)現(xiàn)以下廣受關(guān)注的PHP應(yīng)用程序受到此類(lèi)漏洞的影響(多數(shù)漏洞由Dawid Golunski發(fā)現(xiàn))。
由于一些廣泛使用的Web應(yīng)用程序(如 Wordpress, Joomla和 Drupal)部分模塊基于以上庫(kù)開(kāi)發(fā),所以也會(huì)受到該類(lèi)漏洞的影響。
為什么escapeshellarg()函數(shù)沒(méi)有那么安全?
PHP提供了 escapeshellcmd() 和 escapeshellarg() 函數(shù)用來(lái)過(guò)濾用戶(hù)的輸入,防止惡意攻擊者執(zhí)行其他的系統(tǒng)命令或參數(shù)。直觀來(lái)講,下面的PHP語(yǔ)句看起來(lái)很安全,并且防止了-param1參數(shù)的中斷:
system(escapeshellcmd("./program -param1 ". escapeshellarg( $_GET["arg"] )));
然而,當(dāng)此程序有其他可利用參數(shù)時(shí),那么這行代碼就是不安全的。攻擊者可以通過(guò)注入"foobar" -param2 payload "來(lái)突破-param1參數(shù)的限制。當(dāng)用戶(hù)的輸入經(jīng)過(guò)兩個(gè)escapeshell*函數(shù)的處理,以下字符串將到達(dá)system()函數(shù)。
./program -param1 "foobar""" -param2 payload "
從最終系統(tǒng)執(zhí)行的命令可以看出,兩個(gè)嵌套的轉(zhuǎn)義函數(shù)混淆了引用并允許附加另一個(gè)參數(shù)param2。
PHP的mail()函數(shù)在內(nèi)部使用escapeshellcmd()函數(shù)過(guò)濾傳入的參數(shù),以防止命令注入攻擊。這正是為什么escapeshellarg()函數(shù)不會(huì)阻止mail()函數(shù)的第5個(gè)參數(shù)的攻擊。 Roundcube和 PHPMailer的開(kāi)發(fā)人員率先發(fā)布了針對(duì)該漏洞的補(bǔ)丁。
為什么FILTER_VALIDATE_EMAIL是不安全的?
另一種直接的方法是使用PHP的電子郵件過(guò)濾器(email filter),以確保在mail()函數(shù)的第5個(gè)參數(shù)中只使用有效的電子郵件地址。
filter_var($email, FILTER_VALIDATE_EMAIL)
但是,并不是所有可能存在安全問(wèn)題的字符串都會(huì)被該過(guò)濾器過(guò)濾。它允許使用嵌入雙引號(hào)的轉(zhuǎn)義的空格。
由于函數(shù)底層實(shí)現(xiàn)正則表達(dá)式的原因,filter_var()沒(méi)有對(duì)輸入正確的過(guò)濾,導(dǎo)致構(gòu)造的payload被帶入執(zhí)行。
"a."" -OQueueDirectory=%0D=eval($_GET[c])?> -X/var/www/html/"@a.php
對(duì)于上文給出的url編碼輸入,filter_var()函數(shù)返回true,將該payload識(shí)別為有效的郵件格式。
當(dāng)開(kāi)發(fā)人員使用該函數(shù)驗(yàn)證電子郵件格式作為唯一的安全驗(yàn)證措施,此時(shí)仍然是可以被攻擊者利用的:與我們之前的攻擊方式類(lèi)似,在PHP程序發(fā)送郵件時(shí),我們精心構(gòu)造的惡意“電子郵件地址”會(huì)將將PHP webshell生成在Web服務(wù)根目錄下。
=eval($_GET[c])?>/): No such file or directory
切記,filter_var()不適合用于對(duì)用戶(hù)輸入內(nèi)容的過(guò)濾,因?yàn)樗鼘?duì)部分字符串的驗(yàn)證是不嚴(yán)格的。
如何安全的使用mail()函數(shù)
仔細(xì)分析應(yīng)用程序中傳入mail()函數(shù)的參數(shù),滿(mǎn)足以下條件:
$to 除非可以預(yù)期用戶(hù)的輸入內(nèi)容,否則不直接使用用戶(hù)輸入
$subject 可以安全的使用
$message 可以安全的使用
$additional_headers 過(guò)濾r、n字符
$additional_parameters 禁止用戶(hù)輸入
事實(shí)上,當(dāng)把用戶(hù)的輸入作為shell指令執(zhí)行時(shí),沒(méi)有什么辦法可以保證系統(tǒng)的安全性,千萬(wàn)不要去考驗(yàn)?zāi)愕倪\(yùn)氣。
如果在開(kāi)發(fā)您的應(yīng)用程序過(guò)程中第5個(gè)參數(shù)一定要由用戶(hù)控制,你可以使用電子郵件過(guò)濾器(email filter)將用戶(hù)輸入的合法數(shù)據(jù)限制為最小字符集,即使它違反了RFC合規(guī)性。我們建議不要信任任何轉(zhuǎn)義或引用程序,因?yàn)閾?jù)歷史資料表示 這些功能是存在安全問(wèn)題的,特別是在不同環(huán)境中使用時(shí),可能還會(huì)暴露出其他安全隱患。Paul Buonopane研究出了另一種方法去解決這個(gè)問(wèn)題,可以在 這里找到。
總結(jié)
許多PHP應(yīng)用程序都有向其用戶(hù)發(fā)送電子郵件的功能,例如提醒和通知。 雖然電子郵件頭注入是眾所周知的安全問(wèn)題,但是當(dāng)開(kāi)發(fā)人員使用mail()函數(shù)時(shí),往往會(huì)忽視不正當(dāng)?shù)氖褂糜锌赡軐?dǎo)致遠(yuǎn)程命令執(zhí)行漏洞。 在這篇文章中,我們主要分析了mail()函數(shù)的第5個(gè)參數(shù)使用不當(dāng)可能存在的安全風(fēng)險(xiǎn),以及如何防范這種問(wèn)題,防止服務(wù)器受到攻擊。
本文由甲爪cpa聯(lián)盟(www.jiazhua.com)整理編輯!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/22903.html
摘要:背景項(xiàng)目中通過(guò)遠(yuǎn)程調(diào)用服務(wù)框架調(diào)用了許多其它的服務(wù)其中有一個(gè)服務(wù)需要升級(jí)其升級(jí)不是版本上的升級(jí)而是整個(gè)服務(wù)重新取了一個(gè)名字使用的也是全新的包但是調(diào)用的方法沒(méi)有改變因此在升級(jí)時(shí)只是在調(diào)用服務(wù)類(lèi)中修改了調(diào)用地址和調(diào)用返回實(shí)體由改為該中返回該調(diào)用 背景 項(xiàng)目中通過(guò)遠(yuǎn)程調(diào)用服務(wù)框架調(diào)用了許多其它的服務(wù),其中有一個(gè)服務(wù)wx/subscribe/contract/CircleService 需要升...
摘要:但是在這個(gè)判斷的情況下,則會(huì)很神奇的發(fā)現(xiàn)打印出來(lái)了,說(shuō)明此時(shí)為,為什么呢因?yàn)檫@里執(zhí)行了一個(gè)對(duì)象到布爾值的轉(zhuǎn)換故返回。 ????之前做項(xiàng)目的時(shí)候,總會(huì)處理各式各樣的數(shù)據(jù),來(lái)進(jìn)行繪圖。但是當(dāng)后臺(tái)返回一個(gè)空數(shù)組的時(shí)候,頁(yè)面中并不會(huì)顯示沒(méi)有數(shù)據(jù)的圖。代碼如下: var arr = [] if(arr){console.log(124)}else{console.log(無(wú)數(shù)據(jù))} 我明明判斷了...
摘要:除非使用了分塊編碼,否則首部就是帶有實(shí)體主體的報(bào)文必須使用的。 背景 新項(xiàng)目上線, 發(fā)現(xiàn)一個(gè)奇怪的BUG, 請(qǐng)求接口有很小的概率返回400 Bad Request,拿到日志記錄的請(qǐng)求的參數(shù)于POSTMAN中測(cè)試請(qǐng)求接口, 發(fā)現(xiàn)能夠正常響應(yīng). 排查過(guò)程 首先服務(wù)器能夠正常響應(yīng)400 Bad Request, 排除接口故障問(wèn)題. 對(duì)比日志過(guò)程中發(fā)現(xiàn) { hello:world ...
摘要:項(xiàng)目組長(zhǎng)給我看了一道面試別人的面試題。打鐵趁熱,再來(lái)一道題來(lái)加深下理解。作者以樂(lè)之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVbur0z?w=600&h=400); 剛?cè)肼毿鹿荆瑢儆诠久刃乱幻叮惶煜挛鐚?duì)著屏幕看代碼架構(gòu)時(shí)。BI項(xiàng)目組長(zhǎng)給我看了一道面試別人的JS面試題。 雖然答對(duì)了,但把理由說(shuō)錯(cuò)了,照樣不及格。 ...
摘要:在群里討論,然后得出了這幾種寫(xiě)法,感覺(jué)是層層遞進(jìn),想了想,最后選擇發(fā)布成文章大頭兒子小頭爸爸叫去吃飯大頭兒子小頭爸爸叫去吃飯大頭兒子小頭爸爸叫去吃飯吃完了背小頭兒子回去正在牽著的手正在吃給所有對(duì)象擴(kuò)展一個(gè)繼承的方法繼承爸爸要繼承人的功能正在 在群里討論JavaScript,然后得出了這幾種寫(xiě)法,感覺(jué)是層層遞進(jìn),想了想,最后選擇發(fā)布成文章 ({ baby : 大頭兒子, ...
閱讀 2423·2021-11-16 11:44
閱讀 853·2021-09-10 11:16
閱讀 2228·2019-08-30 15:54
閱讀 1060·2019-08-30 15:53
閱讀 1905·2019-08-30 13:00
閱讀 622·2019-08-29 17:07
閱讀 3514·2019-08-29 16:39
閱讀 3138·2019-08-29 13:30