0 x 01 漏洞描述
LyLme Spage 是一个开源的导航页面,致力于简洁高效无广告的上网导航和搜索入口,支持后台添加链接、自定义搜索引擎等功能。
该系统在 file. php 接口处存在任意文件上传漏洞,未经身份攻击者可通过该漏洞在服务器端任意执行代码、写入后门、获取服务器权限,进而控制整个 web 服务器。
漏洞影响范围:LyLme Spage v 1.9.5
漏洞编号:CVE-2024-34982
fofa 规则:body=”LyLme Spage”
0 x 02 环境搭建
PHP 版本:7.1.9(PHP 版本需 7.1 及以上,不支持 PHP 8)
前往 GitHub - LyLme/lylme_spage: 六零导航页下载最新版本源码压缩包,上传到网站根目录解压
访问http://域名/install
按提示配置数据库进行安装
安装成功后台地址:http://域名/admin
账号密码:admin/123456
0 x 03 漏洞复现
1 | POST /include/file.php HTTP/1.1 |
php 文件,上传为 PNG 格式,发包时修改文件后缀,修改为 php 文件。
访问给出的 URL 地址,可解析 php 文件
0 x 04 漏洞分析
- 定位漏洞文件
- 漏洞文件,位于
/include/file. php
- 也可以根据相应包的内容进行全局搜索。
- 漏洞文件,位于
- 文件验证漏洞点 通过 validate_file_type() 函数对文件的类型进行判断。
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
30function upload_img($upfile)
{
$IMG_NAME = uniqid("img_"); //文件名
$maxsize = pow(1024, 2) * 5;
//文件大小5M
$dir = ROOT . SAVE_PATH . 'upload/';
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
//创建路径
}
$type = $upfile["type"];
$size = $upfile["size"];
$tmp_name = $upfile["tmp_name"];
if (!validate_file_type($type)) {
exit('{"code": "-4","msg":"上传的图片类型不支持"}');
}
$parts = explode('.', $upfile["name"]);
$img_ext = "." . end($parts);
if ($size > $maxsize) {
exit('{"code": "-1","msg":"图片不能超过' . $maxsize / pow(1024, 2) . 'M"}');
}
$img_name = $IMG_NAME . $img_ext;
//文件名
$save_to = $dir . $img_name;
$url = '/' . SAVE_PATH . 'upload/' . $img_name;
if (move_uploaded_file($tmp_name, $dir . $img_name)) {
echo('{"code": "200","msg":"上传成功","url":"' . $url . '"}');
return $dir . $img_name;
}
}从1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function validate_file_type($type)
{
switch ($type) {
case 'jpeg':
$type = 'image/jpeg';
break;
case 'jpg':
$type = 'image/jpeg';
break;
case 'png':
$type = 'image/png';
break;
case 'gif':
$type = 'image/gif';
break;
case 'ico':
$type = 'image/x-icon';
break;
}
$allowed_types = array("image/jpeg", "image/png", "image/gif", "image/x-icon");
return in_array($type, $allowed_types);
}$_FILES["file"]
中获取数组中的 type 字段。然后与白名单数组中的内容进行对比。只要符合白名单中的,便可以顺利上传由此可见,在判断类型时,它只对1
2
3
4
5
6
7
8if (empty($_POST["url"]) && !empty($_FILES["file"])) {
$filename = upload_img($_FILES["file"]);
if (isset($islogin) == 1 && $_GET["crop"] == "no") {
//不压缩图片
exit();
}
//上传图片
}Content-Type: image/png
部分进行了白名单的筛选。
0 x 05 POC 构造
由于只对 Content-Type: image/png 进行检测,所以修改 filename 即可,改为 php 文件。
1 | POST /include/file.php HTTP/1.1 |
0 x 06 修复方案
对 filename,content 都进行检测