[java安全基础 01]SQL+反序列化
tomcat
Servlet
什么是servlet
Java Servlet是运行在 Web 服务器或应用服务器上的程序.它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。
servlet的功能:
- 创建并返回基于客户请求的动态HTML页面
- 与数据库进行通信(业务逻辑处理)
如何使用servlet
servlet本身是一组接口,自定义一个类,并且实现servlet接口,这个类就具备了接受客户端请求以及做出响应的功能
浏览器不能直接访问servlet文件,只能通过映射的方式来简介访问servlet,映射需要开发者手动配置
基于文件的配置方式
基于注解的配置
servlet生命周期
Servlet的层次结构
Servlet >GenericServlet > HttpServletHTTP
请求有很多种类型,常用的有四种:
真正的开发环境中基本只会用到service方法,其他方法没必要写出来,显得冗余,实际上servlet已经提供了部分实现类来帮助高效的编程和维护,所以不需要直接实现servlet接口,只需要继承HttpServlet
重写doGet和doPOST
RESTFUL
GenericServlet 实现 Servlet 接口,同时为它的子类屏蔽了不常用的方法,子类只需要重写service方法即可。HttpServlet继承GenericServlet,根据请求类型进行分发处理,GET进入doGET方法, POST进入 doPOST方法。开发者自定义的Servlet类只需要继承 HttpServlet即可,重新doGET 和doPOST
JSP
jsp本质上就是一个servlet,jsp主要负责用户交互,将最终的界面呈现给用户,html+js+css+ava的混合文件
单纯从开发的角度看,jsp就是在HTML中嵌入java程序,具体的嵌入方式由3种:
- jsp脚本,执行java逻辑代码<% java代码%>
- jsp声明:定义java方法
<%!
声明java 方法
%>
- jsp表达式:把java对象直接输出到HTML页面中
<%= java变量%>
jsp内置对象
request常用方法
dispach分配机制
在同一个请求在服务器的传递(url没有变化),也叫做服务器跳转,和重定向不一样
request重定向
sendRedirect(String path)重定向页面直接的跳转
转发getRequestDispatcher和重定向sendRedirect的区别:
转发是将同一个请求传给下一个页面,重定向是创建一个新的请求传给下一个页面,之前的请求结束生命周期。·
转发:同一个请求在服务器之间传递,地址栏不变,也叫服务器跳转。
重定向:由客户端发送一次新的请求来访问跳转后的目标资源,地址栏改变,也叫客户端跳转。
如果两个页面之间需要通过request 来传值,则必须使用转发,不能使用重定向。用户登录,如果用户名和密码正确,则跳转到首页(转发),并且展示用户名,否则重新回到登陆页面(重定向)
转发,同一个请求在服务器中传递,可以数据传递,但是重定向是客户端发起一次新的请求,url会变化
jsp内置对象作用域
springboot
什么是spring
spring回一个2003年兴起的一个轻量级java开发框架
spring是为了 解决企业级应用开发的复杂性而创建的,简化开发
spring如何简化java开发
为了降低java开发的复杂性,spring采用了以下4种关键策略
- 基于pojo的清零及和最小侵入性编程,所有东西都是bean
- 通过IOC,依赖注入(DI)和面向接口实现松耦合
- 基于切面(AOP)和管理进行声明式编程
- 通过切面和末班减少样式代码,RedisTemplate,XXXtemplate
什么是springboot
Spring框架是Java平台上的一种开源应用框架.提供具有控制反转特性的容器。
Spring Boot基于Spring 开发, Spirng Boot本身并不提供 Spring框架的核心特性以及扩展功能.只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。
约定大于配置的核心思想
Spring Boot的主要优点:
-
为所有Spring开发者更快的入门
-
开箱即用,提供各种默认配翟来简化项目配置
-
内嵌式容器简化Web项目
-
没有冗余代码生成和XML配置的要求
简单来说,springboot就是易于开发的spring
运行原理
pom.xml
主启动类
四个原注解
sql注入
JDBC介绍
java database connectivity是一个独立于特定数据库的管理系统,通用的SQL主句库存取和凑在哦公共接口
定义了一组标准,为访问不同数据库提供了同意的途径
JDBC API
内容:供开发者调用的接口
- DriverManager接口
- Connection接口
- Statement接口
- ResultSet接口
DriverManager类
作用:驱动管理器,主要负责管理驱动
DriverManager负责驱动程序管理,数据库驱动则是为了应用程序服务的,所以DriverManager的重要任务就是提供连接的获取
在调用getConnection方法时,DriverManager会试着从初始化时加载到哪些驱动程序以及使用于当前applet或应用程序相同的类加载器,显示加载的那些驱动程序中查找合适的驱动程序
大乌鱼了,不知道为什么SQL连接不上了,配置2个多小时,解决方法:
照着这个新起了一个项目https://blog.csdn.net/yc11223344/article/details/123226302,然后导入servlet.jar,并且把mysql的那个jar也放到了这里的bin。
大乌鱼了,不知道为什么SQL连接上了,配置了1min,解决方法,把什么mevan包删除完,重新导入tomcat/bin/中的servlet.jar和mysql的那个jar(随便放哪都行)
预编译:
sQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,sQL语句已经被数据库分析编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即便参数里有敏感字符如or '1=1'也数据库会作为一个参数一个字段的属性值来处。理而不会作为一个sQL指令,如此,就起到了sQL注入的作用了
XXE
XXE(XML External Entity Injection)全称为XML外部实体注入当允许引用外部实体且存在输入点时.恶意攻击者即可构造恶意内容访问服务器资源等操作
xml基础知识
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型.是—种允许用户对自己的标记语言进行定义的源语言。此. XML文档结构包括xML声明、DTD文档类型定义(可选)、文档元素
反序列化
java反射
如果是看函数什么的,可以看第二个文章,那里全是代码,这里光是看定义确实难顶。
Java安全很大一部分可以从反序列化漏洞说起,而反序列化漏洞又可以从反射说起。
JAVA反射机制是在运行状态中,对于任意一个类.都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。反射就是把java类中的各种成分映射成一个个的Java对象(体现了java的万物皆对象的思想)
为什么需要反射Java
中的两种编译类型
-
静态编译:在编译时确定类型,绑定对象即通过。
-
动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性。
Java反射是Java被视为动态语言的一个关键性质。
换句话说.程序在运行时的行为都是固定的。如果想在运行时改变.就需要反射这东西了;
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
如何获取反射
1.获取反射中的class对象(java.lang.Class)
2.通过反射创建类对象
3.通过反射获取类属性、方法、构造器
1. 获取反射中的Class对象
在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的Class对象。
Class类对象是:
获取Class类对象有三个方法
-
使用Class.forName静态方法: Class clz = cloass.forName("java.lang.String");
-
使用.class方法 Class clz = String.class;
-
使用类对象的getClass()方法 String str = new String("Hello");Class clz =str.getClass()
forName有两个函数重载:
一个有趣的点:使用功能.class
来创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象;
例子:
加载一个类的时候,首先执行static代码,因为执行的时候会先执行静态方法,接着执行空代码块(又叫,构造代码块,初始化块),最后才会执行构造方法;
2.通过反射创建类的对象
两种方式
通过Class对象的newInstance()方法
通过Constructor对象的newInstance()方法
实例
Person.java
注意:通过CONstructor对象创建类对象可以选择特定构造方法,而通过Class对象则只能使用默认的无参的公有构造方法。
问:如果构造方法私有,如何解决?
3.通过放射获取类属性、方法、构造器
getMethod和invoke方法
- Method Class.getMethod(String name, Class<?>... parameterTypes)的作用是获得对象所声明的公开方法
该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。
标识该方法形参类型。
public Object invoke(Object obj, Object... args)
是Method类的方法
该方法的参数一个是Object类型,也就是调用该方法的对象,第二个参数是一个可变参数类型
getDeclared方法系列的放射
与普通的getMethod,getConstructor区别是
- getMethod系列方法获取的是当前类中所有公共发发,包括父类继承的方法
- getDeclaredMethod系列方法获取的是当期那类中"声明"的方法,是实在写在这个类里的,包括私有的方法,但从父类里继承来的就不包含了
注意:这里使用了一个方法setAccessible,这个是必须的。我们获取到一个私有方法后,必须使用setAccessible修改它的作用域,否在仍然不可调用
java 反序列化
认识Java序列化与反序列化
-
序列化就是把对象的状态信息转换为字节序列(即可以存储或传输的形式)过程
-
反序列化即逆过程,由字节流还原成对象
注: 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序
为什么需要java反序列化?
把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中
在网络上传送对象的字节序列
为什么会产生安全问题?
只要服务端反序列化数据,客户端传递类的readObject中代码就会自动执行,基于攻击者在服务器上运行代码的能力
可能的入口形式:
- 入口类的readObject方法直接调用危险方法(少见)
- 入口类参数包含可控类,该类有危险方法,readObject时调用
- 入口类参数中包含可控类,该类调用其他有危险函数的类
比如类型定义为Object
调用equals、hashcode、toString
重点:相同类型,同名函数
- 构造函数/静态代码块等类加载时隐式执行
共同利用条件:
满足这些的有HashMap等
HashMap
继承序列化:有可能会有需求
参数类型宽泛:有键值对,键值对类型宽泛
重写readObject方法:为什么需要重写:https://juejin.cn/post/6844903954774491144#heading-S
因为:HashMap为了保证键的唯一性,它就要计算键的hashcode(hash值),如果键是对象的话,在不同的JVM里面,不同的机器上,计算的hashcode是不一样的。所以需要将对象拆开,把每一个元素都拿出来单独计算,所以必须重新实现这个readObject方法。
这也是简单说法,具体还是得看看底层
示例
创建一个person类,实现Serializable接口
testMain.java
Person.java
开始调试
下断点,调试,强制步入
F7
F7
F8
F7,选第二个方法readOrdinaryObject
,然后F8,F7看一看
进入之后,F8,看到一个readNoProxyDesc
,F7跟入看看
F8执行到这一句,有一个resolveClass
方法,跟入看看
从名字看,是一个决绝class内容的,这里有一个forName
获取一个全类名
然后跟到上面就行了,然后返回daoreadClassDesc
可以看到这里有一个newInstance
方法,这里就已经在创建对象了
F8到图示,最后会调用readSerialData还原出属性之中的值,F7跟如看看
F7跟入readSerialData
后,F8走几步,走到defaultFiles
,再F7跟入函数
卧槽,发现更错代码了,该跟反序列化Person的,跟成了urldns的,是说怎么全是hashmap
不过前面步骤一样,重新走一遍就好
F7走到此处
这一步是对获取的到fields进行赋值,多走几步F8,好像得先获取一个整型数据,所以又走了很多步骤,但最后都会回到这里
最后的setObjectfileValues
是一个将Person具体还原对象
这就算是勉强跟完了反序列化链,这里就只是跟一下是怎么样的一个流程,在哪里赋值扫盲的。
补充
URLDNS链
反序列化安全问题
如果java应用对用户输出,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行
Ysoserial工具
https://github.com/frohoff/ysoserial
ysoserial集合了各种java反序列化payload,它可以让用户根据自己选择的利用链,生成反序列化利用数据,通过这些数据发送给目标,从而执行用户预先定义的命令
URLDNS链
该链特点
- 使用java内置的类构造,对第三方呢库没有依赖
- 在目标没有回显的时候,能通过DNS请求得知是否存在反序列化漏洞
使用ysoserial工具生成payload
编写测试类执行反序列化:
分析ysoserial工作原理
生成Paylod的类在GeneratePyload.java
在idea的project struction中可以导入jar包,然后在那里看就行
getObject方法里就是gadget链的生成,这里返回的ht对象就是构造完成的恶意对象。
在URLDNS.java中有一个HashMap 定义的ht
考虑到,这是反序列化触发的,所以在HashMap中应该是有个readObject方法,于是点进去看看
开始调试
先不急,首先看到
URLDNS.JAVA文件
还是下断点,然后强制步入
走到此处获取协议,协议为http
F8走几步,此处是获取主机地址
F7步入方法看看
F7继续步入
F8走几步
走到此处,会对域名进行解析返回域名(时间有点久了,估计不行了),然后dns链会接收到请求。(我就在此处下个断点,重新获取一个url),到这里了,也就算是跟完了UELdns
我以为是连接寄了,原来是还得F8走一步
可以在DNSLOG看到:
其它
有个关键字叫transient
,被它修饰的不会参与序列化与反序列化的过程。
在URLDNS.JAVA代码中,就有被它修饰的。这样可以避免在进行序列化和反序列化中访问请求连接。
这个修饰只是在生成payload的时候有修饰
重写了Handler,和其它的方法,都返回了null,或者就是空着不管。免得造成多的请求。
这里点点找找Handler,和它的函数
然后进入URL.java,找到hashCode()
看到是一个handler对象,在看handler的定义
看到了transient,说明这里不参与反序列化
URLDNS反序列化链总结
__EOF__

本文链接:https://www.cnblogs.com/upstream-yu/p/16977292.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix