jarvisoj phpinfo writeup及注入的變數詳解

MK.D.jx發表於2019-03-22

jarvisoj phpinfo writeup及注入的變數詳解

這題目是關於php session反序列化的題目,參考了許多大神的writeup,但是注入點沒有詳細的講解,因此自己想寫一篇witeup

題目探索

首先開啟題目頁面直接獲得原始碼:

// An highlighted block
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
   public $mdzz;
   function __construct()
   {
	   $this->mdzz = 'phpinfo();';
   }
   function __destruct()
   {
	   eval($this->mdzz);
   }
}
if(isset($_GET['phpinfo']))
{
   $m = new OowoO();
}
else
{
   highlight_string(file_get_contents('index.php'));
}
?>

當new一個例項物件,會給屬性mdzz賦值成phpinfo;當銷燬一個例項物件,會執行eval函式,說明我們需要得到一個例項物件,並且我們可以控制mdzz的值,再讓它銷燬,從而執行eval函式。
傳入引數phpinfo,得到對方的配置圖,
在這裡插入圖片描述
結合ini_set(‘session.serialize_handler’, ‘php’);配置中php_serialize的倆個值不同,php是當前指令碼的配置,php_serialize是全域性配置,是php.ini中設定的,可知該問題是php session反序列化問題。如果網站不同的php檔案的寫入Session的序列化方式與讀取Session的反序列化方式不同,就可能導致漏洞的產生
各個配置的解釋

配置 解釋
session.upload_progress.enabled 是否啟用上傳進度報告(預設on),開啟後會在上傳檔案時,將一個表示進度的資料結構傳入$_SESSION
session.upload_progress.cleanup 是否在上傳完成後及時刪除進度資料(預設on,本題需要是off )
session.upload_progress.prefix 預設是upload_progress_
session.upload_progress.name 預設是PHP_SESSION_UPLOAD_PROGRESS
session.serialize_handler 對session進行序列化or反序列化的處理器:php、php_serialize(php>5.5.4)、php_binary
session.save_handler files表示session儲存到會話檔案中

各個處理器的序列化規則

配置 解釋
php 對$_SESSION的每個元素物件單獨呼叫serialize(),儲存在檔案。每個元素儲存格式:鍵名+|+ serialize($_SESSION[‘key’])
php_serialize serialize($_SESSION)返回的字串儲存在會話檔案中
php_binary 對$_SESSION的每個元素物件單獨呼叫serialize(),儲存在檔案。儲存規則:鍵名的長度對應的ASCII值+鍵名+serialize($_SESSION[‘key’])。

上傳進度的資料結構,
進度資料將儲存在$_SESSION[ini_get(“session.upload_progress.prefix”).$_POST[ini_get(“session.upload_progress.name”)]]
如圖:upload_progress_是session.upload_progress.prefix的值,
laruence是$_POST[ini_get(“session.upload_progress.name”)]的值。

在這裡插入圖片描述

注入例項的實現

由phpinfo()頁面繼續可知,session.upload_progress.enabled為On
在這裡插入圖片描述且session.upload_progress.cleanup是off, 這兩個配置決定了該上傳程式的資料結構能儲存在會話檔案中。
自己寫一個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>

抓包如圖
在這裡插入圖片描述
必須有上傳一個引數,名是PHP_SESSION_UPLOAD_PROGRESS,值可以任意,

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

###具體過程的猜想:
上傳檔案時,記錄上傳進度資料到$_SESSION[‘upload_progress_laruence’],以php.ini中的session.serialize_handler指定的序列化方式儲存在會話檔案,
當對filename進行構造payload:
filname="|O:5:\“OowoO\”:1:{s:4:\“mdzz\”;s:20:\“var_dump($_SESSION);\”;}"

filname的字串內容中的雙引號必須加上\進行轉義,否則會和filename=後的雙引號閉合。
在這裡插入圖片描述
下圖,是在本地搭建環境下,檢視會話檔案的儲存內容
在這裡插入圖片描述
選中的字串是filename的值,選中的字串的後面的字串在被php方式反序列化時,會被忽略。

但是當訪問php檔案時,且該檔案帶有ini_set(‘session.serialize_handler’, ‘php’);php檔案將以該方式反序列化session檔案中儲存的資料,從而產生了OowoO類的例項,因為不是new產生的例項,不會執行__construct函式。php檔案執行完後,銷燬物件時,執行__destruct函式。
該php檔案執行結束後,session又以php方式序列化儲存$_SESSION。如圖
在這裡插入圖片描述
豎線後的字元會被反序列化成為例項物件,豎線前的字元作為SESSION陣列中OowoO例項的key,
構造payload的方法:filename=”|serialize(OowoW例項物件)” (注:字串內容中的雙引號要加上\)
payload注入點二
其實不一定要在filename處寫payload,只要使上傳進度的資料中field_name的值是payload,也是可以實現的,field_name對應http報文中的name。嘗試對name寫入payload
在這裡插入圖片描述
返回結果,表明執行了var_dump();
在這裡插入圖片描述

最後,修改payload,使mdzz的值是print_r(scandir(dirname(FILE)));
在這裡插入圖片描述
查出當前目錄的檔案
使mdzz=
print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));
查出flag
在這裡插入圖片描述

轉載請註明出處

參考資料

https://www.cnblogs.com/sijidou/p/10455646.html
https://blog.csdn.net/wy_97/article/details/78430690

相關文章