Open aszx87410 opened 3 years ago
這一題給的程式碼非常簡短:
<?= 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) 可以順利執行。
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 裡面你就可以拿到:
?a[]=1&a[]=2
[]
?a[test]=1
Array ( [test] => 1 )
如果是這樣的話,就可以讓 key 是 /*,value 是 */]); echo 123;/*,組合起來就變成:
*/]); echo 123;/*
<?php Array( [/*] => "*/]); echo 123;/*" ); ?>
就成功組出一段合法的 PHP 程式碼。
這一題學到最有價值的東西就是這個了,原來 query string 不只傳陣列,要傳物件也是可以的(至少 PHP 跟 express 都有支援,其他的我不確定)
這一題給的程式碼非常簡短:
限制看起來很嚴格,長度最多只能到 9,而且還不能有任何英文數字。
之前有解過類似的需要用 xor 或是 not 來產生字元,然後再用 PHP 可以用字串 function 名稱執行函式的特性來執行,最後達成 RCE。
不過這題的長度限制是 9,再怎麼想都不可能,因為光是基本的一些字元就已經超過了。
所以這題換個角度想,可以用 array 來試試看,自己實際試過之後發現 array 確實可以繞過,前面兩個判斷都可以通過,那接下來的問題就是該怎麼讓:
eval(print_r($🐱,1)
可以順利執行。這邊我一開始的想法是讓 print_r 出來的東西變成合法的 php 程式碼,就可以成功執行了,於是我先用 print_r 出來的格式去跑 php,嘗試過底下這樣:
執行之後會輸出:PHP Fatal error: Illegal offset type in /Users/li.hu/Documents/playground/php-test/er.php on line 3
看起來是 array 的 index 不能是陣列,不然就會出錯。原本想說那這條路應該行不通了,後來我想說:「那既然會出錯,有沒有可能在出錯之前先執行我想執行的函式?」,就嘗試了以下程式碼:
發現還真的印出結果了!而且原本的 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) 把 fatal error 變 warning,然後執行想要的程式碼,最後用註解把後面跳掉,成功拿到 flag。
賽後去看其他人的解法,發現 query string 原來這麼神奇。我一直以為 query string 頂多就是傳 array,像是這樣:
?a[]=1&a[]=2
,但後來才發現原來[]
裡面可以有東西,像這樣:?a[test]=1
,在 PHP 裡面你就可以拿到:如果是這樣的話,就可以讓 key 是
/*
,value 是*/]); echo 123;/*
,組合起來就變成:就成功組出一段合法的 PHP 程式碼。
這一題學到最有價值的東西就是這個了,原來 query string 不只傳陣列,要傳物件也是可以的(至少 PHP 跟 express 都有支援,其他的我不確定)