溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PHP中對象注入的示例分析

發(fā)布時間:2021-09-03 09:27:00 來源:億速云 閱讀:104 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下PHP中對象注入的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

前言

雖然這篇文章叫做PHP對象注入,但是本質(zhì)上還是和PHP的序列化的不正確使用有關(guān)。如果你閱讀了PHP中的SESSION反序列化機(jī)制對序列化就會有一個大致的認(rèn)識。PHP對象注入其實(shí)本質(zhì)上也是由于序列化引起的。

基礎(chǔ)知識

在php類中可能會存在一些叫做魔術(shù)函數(shù)(magic 函數(shù)),這些函數(shù)會在類進(jìn)行某些事件的時候自動觸發(fā),例如__construct()會在一個對象被創(chuàng)建時調(diào)用, __destruct()會在一個對象銷毀時調(diào)用, __toString當(dāng)對象被當(dāng)做一個字符串的時候被調(diào)用。常見的魔術(shù)函數(shù)有__construct() 、 __destruct() __toString() 、 __sleep() __wakeup() 。

舉例如下:

<?php
class test{
 public $varr1="abc";
 public $varr2="123";
 public function echoP(){
  echo $this->varr1."<br>";
 }
 public function __construct(){
  echo "__construct<br>";
 }
 public function __destruct(){
  echo "__destruct<br>";
 }
 public function __toString(){
  return "__toString<br>";
 }
 public function __sleep(){
  echo "__sleep<br>";
  return array('varr1','varr2');
 }
 public function __wakeup(){
  echo "__wakeup<br>";
 }
}

$obj = new test();  //實(shí)例化對象,調(diào)用__construct()方法,輸出__construct
$obj->echoP();   //調(diào)用echoP()方法,輸出"abc"
echo $obj;    //obj對象被當(dāng)做字符串輸出,調(diào)用__toString()方法,輸出__toString
$s =serialize($obj);  //obj對象被序列化,調(diào)用__sleep()方法,輸出__sleep
echo unserialize($s);  //$s首先會被反序列化,會調(diào)用__wake()方法,被反序列化出來的對象又被當(dāng)做字符串,就會調(diào)用_toString()方法。
// 腳本結(jié)束又會調(diào)用__destruct()方法,輸出__destruct
?>

原理

為什么會用到序列話這樣的方法?主要就是就是方便進(jìn)行數(shù)據(jù)的傳輸,并且數(shù)據(jù)恢復(fù)之后,數(shù)據(jù)的屬性還不會發(fā)生變化。例如,將一個對象反序列化之后,還是保存了這個對象的所有的信息。同時還可以將序列化的值保存在文件中,這樣需要用的時候就可以直接從文件中讀取數(shù)據(jù)然后進(jìn)行反序列化就可以了。在PHP使用serialize()unserialize()來進(jìn)行序列化和反序列化的。

而序列化的危害就在于如果序列化的內(nèi)容是用戶可控的,那么用戶就可以注入精心構(gòu)造的payload。當(dāng)進(jìn)行發(fā)序列化的時候就有可能會出發(fā)對象中的一些魔術(shù)方法,造成意想不到的危害。

對象注入

本質(zhì)上serialize()unserialize()在PHP內(nèi)部實(shí)現(xiàn)上是沒有漏洞的,漏洞的主要產(chǎn)生是由于應(yīng)用程序在處理對象、魔術(shù)函數(shù)以及序列化相關(guān)問題的時候?qū)е碌摹?br/>

如果在一個程序中,一個類用于臨時將日志存儲進(jìn)某個文件中,當(dāng)__destruct()方法被調(diào)用時,日志文件被刪除。

代碼大致如下:

logfile.php

<?php
class LogClass {
 public $logfilename = "";
 public function logdata($text) {
  echo "log data".$text."<br/>";
  file_put_contents($this->logfilename,$text,FILE_APPEBD);
 }

 public function __destruct() {
  echo 'deletes'.$this->logfilename;
  unlink(dirname(__FILE__).'/'.$this->logfilename);
 }
}
?>

在其他類中使用LogClass

logLogin.php

<?php
include "index.php";
$obj = new LogClass();
$obj->logfilename = "login.log";
$obj->logdata('記錄日志');
?>

上面的這段代碼就是一個正常的使用LogClass類來完成日志記錄的功能。

下面顯示的是存在對象注入漏洞的使用例子。

news.php

<?php
include "logfile.php";
// some codes the use the LogClass
class User {
 public $age = 0;
 public $name = '';
 public function print_data() {
  echo "User".$this->name."is".$this->age."years old.<br/>";
 }
}

// 從用戶接受輸入發(fā)序列化為User對象
$usr = unserialize($_GET["user"]);
?>

上面顯示的代碼使用了LogClass對象同時還會從用戶那里接受輸入進(jìn)行發(fā)序列化轉(zhuǎn)化為一個User對象。

當(dāng)我們提交如下的數(shù)據(jù)

news.php?user=O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John”;}

這樣的語句是可以正常使用的,也是程序員希望使用的方法。

但是如果提交的數(shù)據(jù)為:

news.php?user=O:8:"LogClass":1:{s:11:"logfilename";s:9:".htaccess";}

那么最后就會輸出delete .htaccess。

可以看到通過構(gòu)造的數(shù)據(jù),導(dǎo)致執(zhí)行了LogClass中的__destruct()方法然后刪除了網(wǎng)站中重要的配置文件。

從上面這個例子也可以看出來,如果沒有嚴(yán)格控制用戶的輸入同時對用戶的輸入進(jìn)行了反序列化的操作,那么就有可能會實(shí)現(xiàn)代碼執(zhí)行的漏洞。

注入點(diǎn)

PHP對象注入一般在處在程序的邏輯上面。例如一個User類定義了__toString()用來進(jìn)行格式化輸出,但是也存在File類定義了__toString()方法讀取文件內(nèi)容然后進(jìn)行顯示,那么攻擊者就有可能通過User類的反序列化構(gòu)造一個File類來讀取網(wǎng)站的配置文件。

user.php

<?php
class FileClass {
 public $filename = "error.log";
 public function __toString() {
 echo "filename發(fā)生了變化==>" . $this->filename ;
  return @file_get_contents($this->filename);
 }
}

class UserClass {
 public $age = 0;
 public $name = '';
 public function __toString() {
  return 'User '.$this->name." is ".$this->age.' years old. <br/>';
 }
}

$obj = unserialize($_GET['usr']);
echo $obj;  //調(diào)用obj的__toString()方法
?>

正常情況下我們應(yīng)該傳入UserClass序列化的字符串,例如user.php?usr=O:9:"UserClass":2:{s:3:"age";i:18;s:4:"name";s:3:"Tom";} ,頁面最后就會輸出User Tom is 18 years old. 。

這也是一個理想的使用方法。

PHP中對象注入的示例分析

但是如果我們傳入的數(shù)據(jù)為user.php?usr=O:9:"FileClass":1:{s:8:"filename";s:10:"config.php";} ,頁面最后的輸出是filename發(fā)生了變化==>config.php,執(zhí)行了FileClass中的__toString()方法。

PHP中對象注入的示例分析

這樣就可以讀取到config.php中的源代碼了。

漏洞挖掘

這類洞一般都是很難挖掘的,雖然顯示看起來很簡單,但實(shí)際上需要的條件還是相當(dāng)?shù)目量痰?,而且找對象注入的漏洞一般都是通過審計源代碼的方式來進(jìn)行尋找,看unserialize()的參數(shù)是否是可控的,是否存在反序列化其他參數(shù)對象的可能。

防御

要對程序中的各種邊界條件進(jìn)行測試

避免用戶對于unserialize()參數(shù)是可控的,可以考慮使用json_decode方法來進(jìn)行傳參。

以上是“PHP中對象注入的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI