開源PHPMailer庫被披露存有一個嚴重的遠程代碼執行漏洞。這個漏洞在被修補后,又進行了二次修復,因為第一次沒有充分解決問題。那么,這個漏洞是如何工作的?為什么原始補丁沒有解決問題?
Michael Cobb:代碼庫和框架大大減少了構建新應用程序所需的時間,保存了一些通用組件,因而開發團隊不需要再為每個新項目從頭開始構建。
絕大多數Web服務都是使用流行的第三方框架和庫構建的。這種重復使用代碼的最大問題是,如果在受歡迎的庫中發現了一個漏洞,那么它會影響成千上萬的應用程序、站點和服務。
這種情況非常頻繁,最近又再次出現,前不久Dawid Golunski發現開源運輸類PHPMailer中的遠程代碼執行漏洞。利用該漏洞,攻擊者能夠在Web服務器帳戶的上下文中訪問目標服務器,可能導致Web應用程序受損。
PHPMailer被許多開源項目所使用,如WordPress、Drupal和Joomla,全球約有900萬用戶。網上有數千個代碼段和示例,顯示了如何使用PHPMailer從各種形式(如聯系人或注冊表單)發送電子郵件,但其中大多數包含不安全的代碼行,這讓該漏洞得以被利用,因為它允許任何人偽造From和發件人地址。
PHPMailer使用PHP郵件功能作為發送郵件的默認方法。雖然PHPMailer使用的所有電子郵件地址在使用前都已先行進行驗證,但Golunski發現了“生成一個包含可執行命令的有效‘發件人’電子郵件地址的方式”。雖然“發件人”電子郵件地址應由開發人員設置,但通常都是由用戶自行設置,這非常不好,用戶能夠提交他們選擇的任何電子郵件地址。另外,如果開發人員未對發件人的屬性進行明確的設置,則使用發件人地址。此發件人值將添加到傳遞給PHP郵件功能的第五個參數,該函數無法過濾掉一些可能包含的字符串字面值轉義字符。這樣一來,攻擊者能夠注入包含發送郵件時執行命令的其他參數。
這個漏洞被標記為CVE-2016-10033,PHPMailer開發人員認為在發布的PHPMailer 5.2.18版本時已修復了該漏洞。他們在傳遞給PHP郵件功能之前,添加了escapeshellarg轉義函數來清理發件人地址值。
但Golunski注意到,當escapeshellarg函數與現有的轉義函數escapeshellcmd組合使用時,發件人值仍然沒有得到正確的轉義。通過向原始攻擊代碼添加額外的引用,仍然可以逃避補丁所提供的保護。這個新的漏洞是CVE-2016-10045,補丁在PHPMailer 5.2.20中被發布。
PHPMailer團隊已經在GitHub上發布了如何正確處理網站表單中使用的電子郵件地址的示例。它需要向網站域內的有效地址發送表單數據,并由開發人員設置。
這被認為是一個非常關鍵的漏洞,它顯示出開發人員和Web管理員保持對最新安全威脅以及使用任何共享組件、包或庫訂閱保持警惕的重要性。
開發人員應該審查使用PHPMailer郵件功能的所有腳本,還要研究PHP的各種轉義功能的工作機制,以及它們對不同類型字符串的影響,因為錯誤的轉義字符串也可能導致SQL注入。