1. JAVA
1.1 概念
将保存在磁盘文件中的java字节码重新转换成java对象称为反序列化。
漏洞挖掘中,一旦挖到反序列化漏洞,一般造成的风险极大。java的框架,java的应用程序,使用序列化,反序列化操作非常多。在漏洞挖掘中,代码审计中,安全研究中,反序列化漏洞是个重点项,不可忽视。尤其是java应用程序的RCE,10个里面有7个是因为反序列化导致的RCE漏洞。
序列化与反序列化
package swy.serialTest;
import java.io.Serializable;
public class Student implements Serializable {
private int id;
private String name;
private int gender;
public Student(int id, String name, int gender) {
this.id = id;
this.name = name;
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
import java.io.*;
public class Test {
public static void serialStudent() throws IOException {
Student student = new Student(1, "swy", 1);
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("src/swy/serialTest/1.txt"));
oos.writeObject(student);
System.out.println("序列化成功!");
oos.flush();
oos.close();
}
public static void deserialStudent() throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("src/swy/serialTest/1.txt"));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
// Test.serialStudent();
Test.deserialStudent();
}
}
1.txt文件,序列化结果:
1.2 检测和利用
1.2.1 反序列化
- 利用: Payload生成器(ysoserial)、自定义检测工具或脚本
- 检测:
- 黑盒:数据格式点、特定扫描
- 白盒: 函数点、组件点、代码点
函数点包括:
- ObjectInputStream.readObject
- ObjectInputStream.reaadUnshared
- XMLDecoder.readObject
- XStream.fromXML
- ObjectMapper.readValue
- JSON.parseObject
代码点包括:
- RCE执行
- 数据认证
下方的特征可以作为序列化的标志参考:
一段以rO0Ab开头,基本可以确定这串就是Java序列化base64加密的数据;
或者如果以aced开头,那么它就是这一段Java序列化的16进制。
考虑回显:反弹shell
1.2.2 WebGoat平台java反序列化案例
平台:WebGoat
思路: ipconfig => 序列化 => base64 => rO0Ab格式字符串 最终payload
用ysoserial工具执行下面生成payload:
java -Dhibernate5 -cp hibernate-core-5.4.9.Final.jar;ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.GeneratePayload Hibernate1 “touch 1.txt” > payload.bin
base64解码:
import base64
c=open("C:\\Users\swy\Desktop\payload.bin", "rb").read()
cc=base64.urlsafe_b64encode(c)
open("C:\\Users\swy\Desktop\payload.txt", "wt", encoding="utf-8").write(cc.decode())
最后提交内容。
2. PHP
2.1 概念
PHP中有两个函数serialize()和unserialize()
每个类的定义都以关键字class开头,后面跟着类的名字。一个类可以包含有属于自己的变量,变量以及函数。
类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号“_”开头的,比如_sleep,_wakeup等。
这些函数在某些情况下会自动调用,比如:_construct:当一个对象创建时调用(constructor);_toString:当一个对象被当作一个字符串时使用。
- 技术
- 有类:触发魔术方法
- 无类
- 危害
- SQL注入
- 代码执行
- 目录遍历
常见的魔术方法:
__construct(),类的构造函数
__destruct(),类的析构函数
__call(),在对象中调用一个不可访问方法时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息
PHP反序列化原理:
未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、SQL注入、目录检测等不可控后果。在反序列化的过程中自动触发了某些魔术方法。
当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
2.2 实例
2.2.1 无类问题
环境代码:
<?php
error_reporting(0);
include "flag.php";
$KEY = "swy";
$str = $_GET['str'];
if(unserialize($str) === "$KEY"){
echo "$flag";
}
show_source(_FILE_);
?>
用在线工具生成字符串的反序列化后的结果:
传入参数并访问:
2.2.2 有类问题
代码:
<?php
class ABC {
public $test;
function __construct() {
$test = 1;
echo '调用了构造函数<br>';
}
function __destruct() {
echo '调用了析构函数<br>';
}
function __wakeup() {
echo '调用了苏醒函数<br>';
}
}
echo '创建对象a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser = serialize($a);
echo '反序列化<br>';
$a_unser = unserialize($a_ser);
echo '对象快要死了!';
?>
执行顺序: