PHP mail()可能导致的问题
參考文獻:https://xz.aliyun.com/t/2501
 題目網址:https://www.ripstech.com/php-security-calendar-2017/
環境:
php version < 5.2.0
 phpmailer < 5.2.18
 php 沒有安裝 pcre(no default)
 safe_mode = false(default)
題目
class Mailer {private function sanitize($email) {if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {return '';}return escapeshellarg($email);}public function send($data) {if (!isset($data['to'])) {$data['to'] = 'none@ripstech.com';} else {$data['to'] = $this->sanitize($data['to']);}if (!isset($data['from'])) {$data['from'] = 'none@ripstech.com';} else {$data['from'] = $this->sanitize($data['from']);}if (!isset($data['subject'])) {$data['subject'] = 'No Subject';}if (!isset($data['message'])) {$data['message'] = '';}mail($data['to'], $data['subject'], $data['message'],'', "-f" . $data['from']);} } $mailer = new Mailer(); $mailer->send($_POST);①mail()函數
整體來看此題目是發送郵件的,先看下mail()函數的用法
mail(to,subject,message,headers,parameters) to 必需。規定郵件的接收者。 subject 必需。規定郵件的主題。該參數不能包含任何換行字符。 message 必需。規定要發送的消息。 headers 必需。規定額外的報頭,比如 From, Cc 以及 Bcc。 parameters 必需。規定 sendmail 程序的額外參數。②filter_var()函數
filter_var($email, FILTER_VALIDATE_EMAIL)//郵件過濾器,確保在第5個參數中僅使用有效的電子郵件地址mail()
filter_var(variable, filter, options)函數通過指定的過濾器過濾變量。如果成功,則返回已過濾的數據,如果失敗,則返回 false variable 必需。規定要過濾的變量。 filter 可選。規定要使用的過濾器的 ID。 options 規定包含標志/選項的數組。檢查每個過濾器可能的標志和選項。此函數在雙引號中嵌套轉義空格仍然能夠通過檢測。同時由于底層正則表達式的原因,通過重疊單引號和雙引號,欺騙 filter_var(),這樣就可以繞過檢測。
 一個簡單的例子:
③escapeshellcmd()函數
引入的特殊符號,雖然繞過了filter_var()的檢測,但PHP的mail()在底層調用了 escapeshellcmd() ,對用戶輸入的郵箱地址進行檢測,即使存在特殊符號,也會被 escapeshellcmd()處理轉義,這樣就沒辦法達到命令執行的目的了。
但還調用了escapeshellarg()//把字符串轉碼為可以在 shell 命令里使用的參數,此函數將給字符串增加一個單引號并且能引用或者轉碼任何已經存在的單引號,確保能夠直接將一個字符串傳入 shell 函數(含 exec(),system(),反引號)
 一個例子
- 傳入的參數是127.0.0.1' -v -d a=1
- escapeshellarg()先對單引號轉義,再用單引號將左右兩部分括起來從而起到連接的作用。處理之后為:'127.0.0.1'\'' -v -d a=1'
- 接著escapeshellcmd()對第二步處理后字符串中的 \以及 a=1'中的單引號進行轉義處理,結果為:'127.0.0.1'\\'' -v -d a=1\'
- 第三步處理之后的payload中的\\被解釋成了\而不再是轉義字符,所以單引號配對連接之后將payload分割為三個部分:
 '127.0.0.1'\
 \'' -v -d
 a=1\'
- 所以這個payload可以簡化為curl 127.0.0.1\ -v -d a=1',即向 127.0.0.1\發起請求,POST 數據為 a=1' 。
根據此漏洞有兩個實例:
CVE-2016-10033
payload:
a( -OQueueDirectory=/tmp -X/var/www/html/x.php )@a.com
然后通過 linux 自身的 sendmail 寫log的方式,把log寫到web根目錄下。將日志文件后綴定義為 .php ,即可成功寫入webshell。
CVE-2016-10045
payload:
總結
以上是生活随笔為你收集整理的PHP mail()可能导致的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【重构】微信小程序倒计时组件
- 下一篇: N-Gram的基本原理
