反序列化

简介

什么是反序列话,简单来说就是

  • 序列化:就是将对象转化成字节序列的过程。
  • 反序列化:就是讲字节序列转化成对象的过程。

为什么有序列化呢????,主要有两方面

  • 持久化:对象是存储在JVM中的堆区的,但是如果JVM停止运行了,对象也不存在了。序列化可以将对象转化成字节序列,可以写进硬盘文件中实现持久化。在新开启的JVM中可以读取字节序列进行反序列化成对象。
  • 网络传输:网络直接传输数据,但是无法直接传输对象,可在传输前序列化,传输完成后反序列化成对象。所以所有可在网络上传输的对象都必须是可序列化的。

总而言之,就是能将正向的对象 进行反向转换,哪它有什么危害呢?

  • 不安全的反序列化,主要造成的危害是远程代码执行
  • 如果无法远程代码执行,也可能导致权限提升、任意文件读取、拒绝服务攻击等
  • 也可能会造成远程命令执行,getshell。

实验案例:

1
2
3
4
5
6
<?php
$user=array('carrot','is','good');
$user=serialize($user);
echo($user.PHP_EOL);
print_r(unserialize($user));
?>

以最简单的例子来讲解反序列化

运行成功显示:

1
2
3
4
5
6
7
a:3:{i:0;s:6:"carrot";i:1;s:2:"is";i:2;s:4:"good";}
Array
(
[0] => carrot
[1] => is
[2] => good
)
1
2
3
4
5
6
a:3:{i:0;s:6:"carrot";i:1;s:2:"is";i:2;s:4:"good";}
a:array代表是数组,后面的3说明有三个属性
i:代表是整型数据int,后面的0是数组下标
s:代表是字符串,后面的6是因为carrot长度为6
依次类推

这是个正常输出的内容,我们注意到这个函数 unserialize() 就是将对象进行反序列化

那我们也可以让他正着输出就是serialize()

1
2
3
4
5
6
7
8
9
10
<?php
class test{
public $a;
public $b;
function __construct(){$this->a = "carrotisgood";$this->b="carrotnotgood";}
function happy(){return $this->a;}
}
$a = new test();
echo serialize($a);
?>

运行:

O代表Object是对象,也是类

1
O:4:"test":2:{s:1:"a";s:12:"carrotisgood";s:1:"b";s:13:"carrotnotgood";}

反序列化中常见的魔术方法

1
2
3
4
5
6
__wakeup() //执行unserialize()时,先会调用这个函数__sleep() //执行serialize()时,先会调用这个函数
__destruct() //对象被销毁时触发__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发

防御方式

• 应该尽量避免用户输入反序列化的参数
• 如果确实需要对不受信任的数据源进行反序列化,需要确保数据未被篡改,比如使用数字签名来检查数据的完整性
• 严格控制反序列化相关函数的参数,坚持用户所输入的信息都是不可靠的原则
• 对于反序列化后的变量内容进行检查,以确定内容没有被污染
• 做好代码审计相关工作,提高开发人员的安全意识

不足的日志记录和监控

日志记录是一个系统的最重要的功能之一。日志记录包括登录成功记录、登录失败记录、访问控制记录等,用来记录服务器的各种信息。

攻击原理

攻击者依靠监控的不足和响应的不及时来达成他们的目标而不被知晓。比如日志没有记录登录失败,那么攻击者可能就可以通过暴力破解多次进行登录尝试,但是日志中却没有记录。这就可能让攻击者成功入侵系统并隐匿自己的行踪。这个看似危害不大但却是十分严重的危害,因为一个日志系统不完善的服务器很容易遭受攻击并且在遭受攻击后无法判断攻击来源,这样就无法做出相应的防御,很可能再次遭受同样的攻击。

这种简单来讲就是,在登入的时候没有进行监控防御,导致攻击者可以无数次的进行密码暴破从而获取管理权限。

防御方法

  • 确保所有登录、访问控制失败、输入验证失败能够被记录到日志中去,并保留足够的用户上下文信息,以识别可疑或恶意帐户,并为后期取证预留足够时间
  • 建立有效的监控和告警机制,使可疑活动在可接受的时间内被发现和应对
  • 完善日志系统,使其可以监控各种日志信息
  • 及时对日志系统进行备份,并保存足够长时间

使用含有已知漏洞的组件

​ 这种就是出现Nday漏洞了,需要实时更新服务端、组件的版本。拥有和应用程序相同的权限。如果应用程序中含有已知漏洞的组件被攻击者利用,可能会造成严重的数据丢失或服务器接管。同时,使用含有已知漏洞的组件的应用程序和API可能会破坏应用程序防御、造成各种攻击并产生严重影响。

案例1

例如

  • 最经典的永恒之蓝漏洞,永恒之蓝-MS17010 CVE-2017-0146只要是 17年4月以下的系统都会受到攻击,直接获取最高权限
  • WinRAR 0day漏洞允许攻击者创建恶意 .RAR 和 .ZIP 存档,这些存档显示看似无害的诱饵文件,例如 JPG (.jpg) 图像、文本文件 (.txt) 或 PDF (.pdf),用户双击使用winRAR打开查看压缩文件,并在winRAR窗口中点击查看时触发漏洞

防护方式

  • 识别正在使用的组件和版本,包括所有的依赖
  • 更新组件或引用的库文件到最新
  • 建立安全策略来管理组件的使用