# PHP101 - wargame[.]vn ## chall 01 - Welcome ![image](https://hackmd.io/_uploads/B1eXKIPwlyl.png) `FLAG{ddf1ea89-cd89-4da3-98bc-08028ac4dc7e}` ## chall 02 ```php <?php include __DIR__.'/../../secret.php'; error_reporting(0); highlight_file(__FILE__); die(base64_encode(hex2bin(strrev(bin2hex(str_rot13(print_flag(2))))))); 1wc39mNzY4NDE1NTk9JD5vbm0mNDQ0PSQ5MHU9L2g+YHQ2NTB7dF5JU1 ``` - decode đoạn mã: ```php print(str_rot13(hex2bin(strrev(bin2hex(base64_decode($text)))))); ``` `FLAG{c564ca8b-5c94-4446-aba4-955148676bfc}` ## chall 03 ```php <?php if(isset($_GET['number'])) { $number = $_GET['number']; if ($number === '1337'){ die('No'); } if (intval($number, 0) === 1337){ die(print_flag(3)); } } ``` - `GET /challenge/3/?number=%20%201337` - `%20` là dấu cách `space` - cũng có thể truyền input là `1337blabla...` vì intval() với string gặp ký tự khác digit sẽ dừng. [link](https://www.php.net/manual/en/function.intval.php) ![{50A1525F-DF9E-4AE9-9E4D-B56799CDFB9C}](https://hackmd.io/_uploads/Hy4gxGmZ1g.png) ![image](https://hackmd.io/_uploads/HkZFiDDl1x.png) `FLAG{554382f3-960e-4859-9c79-c64ecd4445e7}` ## chall 04 ```php <?php if(isset($_GET[0]) && isset($_GET[1])){ if($_GET[0] != $_GET[1]){ if (md5($_GET[0]) === md5($_GET[1])){ die(print_flag(4)); } } } ``` - đây là php magic hash - ~~lấy một cặp hash md5 bất kỳ~~ [link](https://github.com/spaze/hashes) ![{E975D849-6A18-4F82-9A17-29B00013772C}](https://hackmd.io/_uploads/SkKpKrk-kg.png) `FLAG{82104890-f270-4d27-b4e4-638a940ffdcf}` #### ngộ nhận - hash collision có là do php loose comparision( hai dấu `==` ) ![image](https://hackmd.io/_uploads/Sk1xiH1bJl.png) - ở chall 04 này so sánh chặt `===`? thì sẽ lấy cặp real collision ![{FEE0852B-959A-4EAA-87E0-B8D015907B97}](https://hackmd.io/_uploads/HkZwsrJWkg.png) ![{C31D3BD4-49FC-49F4-8E63-3D2FBBC75C9E}](https://hackmd.io/_uploads/HJE2oSyWJe.png) - cũng có thể truyền hai mảng vào > GET /challenge/4/?0[]=foo&1[]=bar vì md5() không thể hash kiểu dữ liệu array sẽ trả về NULL, và NULL === NULL -> flag ## chall 05 ```php! if(isset($_GET['inp'])){ $inp = $_GET['inp']; if(((array)simplexml_load_string(file_get_contents($inp))->f->l->a->g)[0] === 'flagggggggggggggg') { die(print_flag(5)); } } ``` - lấy data qua hàm file_get_contents() - convert to xml - access attribute con lần lượt f -> l -> a -> g - convert to array và check nếu array[0] === 'flagggggggggggggg' => vậy có thể dựng xml với content như sau `<root><f><l><a><g>flagggggggggggggg</g></a></l></f></root>` ![{40675EE0-DF02-4626-A1E6-54ECF7EF6ABE}](https://hackmd.io/_uploads/ryMMnvkZye.png) - hàm simple_xml_load_string() nhận data từ hàm file_get_contents(). - file_get_contents() hỗ trợ remote file. ta dựng httpserver host file xml, và public ra ngoài bằng ngrok - GET /challenge/5/index.php?inp=`https://e961-113-185-53-220.ngrok-free.app/file_xml` ![{577153CC-0C36-4AAD-96C3-C05328877C67}](https://hackmd.io/_uploads/ByU-xO1b1e.png) `FLAG{19ee9d17-7f23-4c03-b702-4276246ccdb2}` ## chall 06 ```php! if(isset($_GET['number'])){ $number = $_GET['number']; if(preg_match('/[0-9]/', $number)){ die('waf'); } elseif (intval($number)){ die(print_flag(6)); } } ``` - regex check nếu input chứa số 0 tới 9 thì die - và nếu intval() return true thì có flag - thử search qua hàm intval()![{28A8B3F5-54EC-42B5-A071-98C374AD9281}](https://hackmd.io/_uploads/Sya7-MQZ1l.png) - nếu truyền mảng number[] preg_match() không thể match và return false(với php 8. trở lên báo lỗi và dừng chương trình) ![{719F36A0-E237-4F11-B2A6-9F230BE6D224}](https://hackmd.io/_uploads/SyphMz7Zyx.png) >php 7.4.3 ![{33BA435A-9B38-46CB-9409-26C249BDA676}](https://hackmd.io/_uploads/BJfVQfmWJg.png) >php 8.0.0 ![{B97E825E-6F0B-486B-9EE7-7E281BEFB0CB}](https://hackmd.io/_uploads/rJ8CHOyW1g.png) `FLAG{2352ca3b-c94e-450b-b69a-1938cab26571}` - mình có ý tưởng truyền get param vào vì đọc được 1 bài viêt của a thanhlocpanda ![{3FD067C5-AA1E-4597-87C9-B86B9D79F397}](https://hackmd.io/_uploads/r1i8vuJbJe.png) ## chall 07 ## chall 08 ```php! if(isset($_GET['u'])){ if(preg_match('/admin/', $_GET['u'])) die('no no no'); $u = urldecode($_GET['u']); if($u == 'admin'){ die(print_flag(8)); } } ``` - nếu match input có từ `admin` thì die; - sau đó decode $u, lại so sánh tiếp `u == 'admin'`? true thì trả flag - vậy encode url 2 lần: ![image](https://hackmd.io/_uploads/Hk3afYkW1l.png) ![{62825FF3-BB59-4517-A91A-AF5C9FB59C48}](https://hackmd.io/_uploads/SyKcfF1W1x.png) `FLAG{0406eb88-39ce-4dcc-bace-b058a7e57dd0}` ## chall 09 ```php= if(isset($_GET['say']) && strlen($_GET['say']) < 28){ $say = preg_replace('/^(.*)flag(.*)$/', 'waf', $_GET['say']); if(preg_match('/give_me_the_flag/', $say)){ die(print_flag(9)); } } ``` - regex check: `^` là check ở đầu dòng, `$` là kết thúc dòng ![{72641F4C-FE99-4B29-B12B-50E7233FD9EA}](https://hackmd.io/_uploads/SyjZ_tkb1x.png) - nếu input có nhiều dòng, regex match trên sẽ trả về false ![{FB01A001-CBC9-42F5-AFE1-411DDF77841D}](https://hackmd.io/_uploads/rkE8OKJWyg.png) >expect `waf` instead of `flag here` - `/^(.*)flag(.*)$/` không hoạt động như ý vì khi preg_match() dùng regex có `^`, nó chỉ check dòng đầu tiên thôi, nếu payload có nhiều dòng thì sẽ bypass dễ dàng ![{863F6B69-DCCE-49EE-8BE5-06190624D386}](https://hackmd.io/_uploads/B1Tr4Y1Zyx.png) `FLAG{62e0d117-93af-4e36-957c-3841d1ae7100}` - dựng local ## chall 10 ... ```php= <?php include __DIR__.'/../../secret.php'; error_reporting(0); class Get_Flag{ public $get = True; public function __destruct(){ if($this->get === True){ die(print_flag(10)); } } public function __wakeup(){ $this->get = False; } } if(isset($_GET['get_flag.php'])){ unserialize($_GET['get_flag.php']); } highlight_file(__F ``` sử dụng fast destruct [link](https://github.com/ambionics/phpggc?tab=readme-ov-file#fast-destruct)