Ref#
Vulnerable#
SQL_INJECTION#
注入点 1#
- SqlMapper. xml
<mapper namespace="com.publiccms.logic.mapper.tools.SqlMapper">
<select id="select" parameterType="String" resultType="map">
${sql}
</select>
<select id="query" parameterType="String" resultType="map">
${sql}
</select>
<insert id="insert" parameterType="String">
${sql}
</insert>
<update id="update" parameterType="String">
${sql}
</update>
<delete id="delete" parameterType="String">
${sql}
</delete>
</mapper>反向寻找接口
com.publiccms.logic.service.tools.SqlService#update(及 insert/delete/select)com.publiccms.controller.admin.sys.SysSiteAdminController#execSql
@RequestMapping("execSql")
@Csrf
public String execSql(@RequestAttribute SysSite site, @SessionAttribute SysUser admin, String sql, HttpServletRequest request,
ModelMap model) {
if (ControllerUtils.verifyCustom("noright", !siteComponent.isMaster(site.getId()), model)) {
return CommonConstants.TEMPLATE_ERROR;
}
if (sql.contains(CommonConstants.BLANK_SPACE)) {
String type = sql.substring(0, sql.indexOf(CommonConstants.BLANK_SPACE));
try {
if ("update".equalsIgnoreCase(type)) {
model.addAttribute("result", sqlService.update(sql));
} else if ("insert".equalsIgnoreCase(type)) {
model.addAttribute("result", sqlService.insert(sql));
} else if ("delete".equalsIgnoreCase(type)) {
model.addAttribute("result", sqlService.delete(sql));
} else {
model.addAttribute("result", JsonUtils.getString(sqlService.select(sql)));
}
} catch (Exception e) {
model.addAttribute("error", e.getMessage());
}
model.addAttribute("sql", sql);
// ...
}
return CommonConstants.TEMPLATE_DONE;
}触发机制分析:
接口直接接收用户传入的 sql 字符串参数,仅做了一层简单的前缀判断截取就直接分发给由 MyBatis 代理的底层 sqlService 。而在 SqlMapper. xml 文件中,对所有的传入参数都直接使用 ${sql} 模板字符串进行拼接(未预编译),这就导致获得了后台管理权限的攻击者可以拼接执行恶意的系统和数据库操作 SQL 语句。
SSRF#
触发点#
- UeditorAdminController. java
@RequestMapping(params = "action=" + ACTION_CATCHIMAGE)
@ResponseBody
public Map<String, Object> catchimage(@RequestAttribute SysSite site, @SessionAttribute SysUser admin,
HttpServletRequest request, HttpSession session) {
try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(CommonConstants.defaultRequestConfig).build();) {
String[] files = request.getParameterValues(FIELD_NAME + "[]"); // FIELD_NAME = "file"
if (CommonUtils.notEmpty(files)) {
List<Map<String, Object>> list = new ArrayList<>();
for (String image : files) {
HttpGet httpget = new HttpGet(image);
CloseableHttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (null != entity) {
BufferedInputStream inputStream = new BufferedInputStream(entity.getContent());
FileType fileType = FileTypeDetector.detectFileType(inputStream);
String suffix = fileType.getCommonExtension();
if (CommonUtils.notEmpty(suffix)) {
String fileName = CmsFileUtils.getUploadFileName(suffix);
String filePath = siteComponent.getWebFilePath(site, fileName);
CmsFileUtils.copyInputStreamToFile(inputStream, filePath);
// ...
map.put("source", image);
list.add(map);
}
}
EntityUtils.consume(entity);
}
// ...
return map;
}
} // ...
}反向寻找接口
- 业务逻辑全部于控制器中直接实现。
com.publiccms.controller.admin.sys.UeditorAdminController#catchimage
触发机制分析:
该漏洞位于 Ueditor 的远程图片抓取功能接口。当用户通过 file[] 参数传入一个或多个远程 URL 列表时,后台在未对目标域是否安全、协议是否被允许(是否有针对内网 IP 进行限制等)做出任何有效校验的情况下,直接实例化了 HttpGet 对象并通过 httpclient.execute(httpget) 发起了请求。因此恶意构造 URL 可以令服务器充当跳板发起 SSRF 攻击盲打由于网络隔离无法到达的服务。