# 網路安全 HW1 ###### tags: `class note` ## EASY ### 1. Hello_CTF #### 解題思路 這題應該是要告訴我們密碼的格式都是`EENS{XXX}` ,答案就寫在題目上 ### 2. You can't type #### 問題分析 這個題目提供一個 `korea.PNG` 檔案給我們下載,下載下來後將圖片打開後會發現密碼就寫在圖片中,但密碼中包含韓文,大部分的同學不認得韓文且又不能直接複製中的文字。 #### 解題思路 現在線上有提供很多識別圖片中文字的工具,這次作業使用的是 `Free Online OCR Service` 這個工具,將圖片放上往站上後,網站就會給你圖片中的文字。 >參考網址 >[FREE ONLINE OCR SERVICE] (https://www.onlineocr.net/) > ### 3. Guess a password #### 問題分析 題目中提供一個 `rn.jpg` 檔案給我們下載,但下載下來之後卻沒有辦法將檔案直接開啟。 #### 解題思路 上課中老師有講到有些題目可能會故意將檔案格式隨意轉換以誤導解題者,因此我就試著用 `vim` 編輯器將 `rn.jpg` 打開,並搜尋是否有 `EENS` 關鍵字,果真找到密碼所在處 ![](https://i.imgur.com/k5KMkS9.png) ## Crypto ### 1. sha1 #### 問題分析 將 `sha1` 關鍵字丟到 google 搜尋可以得知 `sha1` 是一個用來對文件加密的 `hash function` ,理想上一份文件經過 `sha1` 運算後只會得到唯一一個值,且不會有任何兩個檔案對應到重複的 `hash` 值。但後來研究發現 `sha1` 存在理論上的缺陷,`Google` 在 2017 年成功實現者個缺陷,產生出兩分 `pdf` 檔案,且這兩份檔案經過 `sha1` 運算後會產生同樣一個 `hash` 值。 根據 Google 到的資訊,還有題目要我們輸入兩個 `secret` 而判斷,此題應該是要將 Google 釋出的兩份文件分別輸入進去。 >參考網址 [史上第一例!Google破解SHA1實現碰撞攻擊] (https://www.ithome.com.tw/news/112347) > #### 解題過程 至於要以什麼樣的格式將文件輸入進去,又要將多大的篇幅輸入進去就必須要做更進一步的分析,分析的結論如下標題,並會將分析過程詳述在內文中。 1. 需要使用 `base64` 先對要輸入進去的 `secret` 進行加密 - 嘗試輸入 `secret` 後會發現錯誤提示如下 ![](https://i.imgur.com/7vljivr.png) - 根據錯誤訊息可以得知我們輸入的 `secret` 會先經過 `base64` 解碼 - 因此推論出輸入的 `secret` 必須是經過 `base64` 加密過得密文 2. 只需要取兩份 `pdf` 檔案中前 320 個 byte 的加密結果分別當作兩個 `secret` 輸入即可 - 撰寫以下 `python` 程式,讀取兩份 `pdf` 檔案並做 `sha1` 後比對結果,發現只要讀取前面 320 個以上的字元數進行 `sha1` 加密都會得到相同的密文 ```python= from hashlib import sha1 import base64 pdf1 = open("./shattered-1.pdf",'rb').read(320) pdf2 = open("./shattered-2.pdf", 'rb').read(320) print(sha1(pdf1).hexdigest()) print(sha1(pdf2).hexdigest()) ``` - 根據 `1.` 得結論,將兩份 `pdf` 檔案分別讀取最前面 320 bytes ,並分別將其透過 `base64` 加密後當成 `secret` 輸入即可得到 flag ```python= from hashlib import sha1 import base64 pdf1 = open("./shattered-1.pdf",'rb').read() pdf2 = open("./shattered-2.pdf", 'rb').read(320) print(base64.b64encode(pdf1)) print(base64.b64encode(pdf2)) ``` >參考資料 [SHA1] (https://ctf-wiki.github.io/ctf-wiki/crypto/hash/sha1-zh/) [We have broken SHA-1 in practice.] (https://shattered.io/)(檔案下載位址) > ### 2. Translate Me #### 問題分析 題目中提供一個 `cipher.txt` 檔案提供給我們下載,檔案內提供了一組加密過後的密文,以及用來加密的 `Key` 並把加密方式也詳述在檔案內。理論上可以透過查表的方式直接姐密,但非常耗時。 #### 解題過程 再根據題目中給的提示 `This encryption wasn't attributed to Blaise de Vigenère.` ,用搜尋引擎查詢 `Blaise de Vigenère` 會發現這位作者所發明的加密法和 `cipher.txt` 內的加密法一模一樣,此加密法名稱為 `Vigenère cipher`。 因此,上網找到了線上解碼器,並將密文以及 KEY 丟入解碼器中得到 flag。 >參考連結 >[Cryptii] (https://cryptii.com/pipes/vigenere-cipher?fbclid=IwAR2HjNh0dZFAKztyYXqJD-Sw3gUV_SDd0Gb0wDWDmoL_FnhPldsAbtrVWuE)(線上解碼器) >[Blaise de Vigenère] (https://en.wikipedia.org/wiki/Blaise_de_Vigen%C3%A8re) > ## PWN ### Could you login #### 問題解析 題目中提供了 `pwn_1.c` 和 `a.out` ,嘗試幾次後覺得 `server` 上跑得檔案就是題目中提供的 `a.out` ,且 `a.out` 就是由 `pwn_1.c` 編譯出的執行檔。因此我們需要先了解 `pwn_1.c` 檔案中做了什麼。 - `pwn_1.c` 內容 - 從程式碼中可以看到,這隻程式會要求使用者輸入 `username` 和 `password` ,並將使用者輸入的結果和 `secret.txt` 內的值比對,唯有 `username` 和 `password` 都和 `secret.txt` 內的值相同才會將 `allow` 設為 `yes` ,最後判斷若 `allow` 為 `yes` 就會印出 `flag` #### 解題過程 因為此題被分類在 `PWN` 中,猜想可能跟記憶體的操作有關,由程式中可以發現 `acc`、`pass` 、`allow` 三者變數是依序著宣告的,因此它們所被分到的記憶體位址很有可能是連續的。因此可以透過 overflow 的方式把 `allow` 的值設成 `yes` ,如此一來即使 `username` 和 `password` 比對錯誤,依然可以拿到 `flag`。但是,`char array` 當作 `global variable` 宣告時資料如何做 `alignment` 的並不是很清楚,所以決定把三個字元陣列的起使位置印出來看。 印出來後會發現 `acc` 和 `pass` 的記憶體位址差了 16 ,而 `pass` 和 `allow` 的記憶體位址差了 `10` ,因此我們只要在輸入密碼時,前面任意輸入 10 個字元,後面再接上 `yes` ,就可以順利用資料 overflow 的特性將 `allow` 設成 `yes`。 ## MISC ### 1. God of Mental Arithmetic #### 問題解析 連上 server 後會要求我們要連續答對 100 題數學運算,且每題都要在極短的時間內作答完,如此一來才會得到 `flag` 。雖然人類很難有辦法在這麼短的時間內連續算出 100 題數學題目並把答案用鍵盤輸入進去,但這對於電腦來說是非常簡單的事,因此希望能夠寫一隻程式讀進題目,並把答案傳送回去給 server。 #### 解題過程 用 python 提供有關 socket 的 API ,將 server 的題目透過 socket 傳送到本地端,運算完答案後透過 socket 將答案傳送回去給 server,實做程式碼如下: ```python= from pwn import * server = remote('140.116.215.203', 5005) while True: string = server.recvline(keepends=False) print(string) if string.endswith(b'?'): ans = str(eval(string[:-4])) server.sendline(ans) print(ans) ``` 上述程一開始先連接 remote server ,在 `while loop` 中持續讀取 server 傳送過來的訊息,並透過 `?` 來確定是否讀到要計算的算式,再透過 `eval` 函式直接進行運算,並將結果傳送回去。 ### 2. Kids doodle #### 問題解析 題目附上一個 `flag.png` 檔案,但直接雙擊檔案卻無法將檔案開啟。上網搜尋了一下發現各個格式的檔案最前面都有一組 `magic number` ,若 `magic number` 不對會導致無法辨認出此檔案內容。 #### 解題過程 根據上述邏輯,將 `png` 透過 `vim` 編輯器將 `flag.png` 開啟,並轉成 可讀的 16 進位格式,發現最前面的 `magic number` 的確被動過手腳,講之改回即可得到一個 QR code ,再將此 QR code 夠過 base64 線上解碼器解碼後即可得到 flag。 >參考資料 >[Digital Investigation] (https://asecuritysite.com/forensics/magic) > ### 3. zip the zip #### 問題解析 將題目所提供的 `zip` 檔下載下來後,會發現解壓縮此檔案需要一組密碼,上網搜尋一下類似的問題,發現有工具可以暴力破解 zip 的密碼,且 Kali 上已經裝好此工具 `Fcrackzip`。但若直接使用此工具暴力破解密碼,此工具要跑得排列組合還是太多種,需要大量的時間才有可能破解完。再仔細看題目給的提示發現 `password is in the dictionary, rockyou` 這個提示,上網 google 一下會發現真的有一個叫做 `rockyou` 的 `dictionary` ,此字典裡收錄了許多常用的密碼。 #### 解題過程 上網下載 dictionary `rockyou.txt` ,並使用 kali 上的 Fcrackzip 進行暴力破解,指令如下: ``` fcrackzip -D -p rockyou.txt -u Have_a__try.zip ``` 解壓縮完後的 `txt` 檔內及存放了 `flag` ### 4. Go upstairs without elevator #### 問題解析 將題目所提供的 `10.zip` 下載下來後會發現此 `zip` 需要密碼才能夠解壓縮,且此檔案內存放的檔案還是一個 `zip` 檔案,另外還有一點值得注意的是 `zip` 檔案內的檔名為一條數學運算式,因此嘗試將 `zip` 檔案內的數學運算式解出來的結果當作密碼,還有自己本身的檔名當作密碼嘗試解壓縮,嘗試過後發現密碼即是檔案名稱 `10` 。再繼續嘗試下去會發現每個 `zip` 檔案的密碼都是自己檔名數學運算式的計算結果。 #### 解題過程 發現上述規律之後,其實可以寫程式自動加以解壓縮,但根據提示 `It's okay to fall down ten times.` 可以發現總共只要解壓縮 10 次,因此就決定直接手動解出 `flag` ,若此壓縮檔案有更多層,應該就會考慮寫一隻程式進行解壓縮。 ## REVERSE ### Eat more and more #### 問題解析 將題目所提供的 `a.out` 下載下來執行後,會發現這是一個貪食蛇的遊戲,遊戲歸則是要得到超過 500 分才能夠拿到 flag。考慮到要手動拿到 500 分難度非常的高,因此一開始就排除了這個方法,上網搜尋一下類似題目,得知 CTF 中 Reverse 的題目通常需要經過 decompiler 去觀察組合語言,並通過 debugger 軟體在程式執行的過程中更改 reg 的值。 #### 解題過程 1. 下載 idafree--7.0 - 此為一個 decompiler ,能將執行檔反組譯成組合語言 - [IDA Freeware Download Page] (https://www.hex-rays.com/products/ida/support/download_freeware/) 2. 觀察反組譯後的程式碼 - ![](https://i.imgur.com/2HZh6tE.png) - 左邊中顯示的是各個 function 的名字 - 大致瀏覽過後發現判斷是否得到超過 500 分的程式應該在 display_screen 函式內 3. 觀察 display_screen - ![](https://i.imgur.com/NR8lJ6Q.png) - 從這部份的組合語言可以發現倒數第四及第三行將 memory 中存放的 `scores` 及 `target` 變數透過 `mov` 指令分別搬到 `edx` 以及 `eax` 暫存器當中 - 倒數第二行則透過 `cmp` 指令比較兩暫存器的值 - 看到這裡大膽猜測這裡就是判斷分數是否已經超過 500 的函式,因此透過工具查詢這段程式碼的位置,如下圖 4. 找到要下中斷點的程式位置 - ![](https://i.imgur.com/tPNlTAR.png) - 根據前面推論,我們要將中斷點設在 `cmp edx, eax` - 根據上圖可以知道,這段指令的位址為 `display_screen+273` (要注意這裡的 273 是 16 進位) 5. 透過 gdb 偵錯 `a.out` ,並更改 register 的值以取得 flag ``` gdb a.out b *(display_screen + 0x273) r info r set $edx=501 c ``` - 透過 gdb 執行 `a.out` 之後將中斷點打在剛剛查到的位置 `display_screen + 0x273` - 透過 gdb 提供的 `info r` 指令查看目前所有 register 的值 - 透過 gdb 提供的 `set $edx=501` 指令將暫存器 `edx` 的值設成 501 - 透過 gdb 提供的 `c` 指令繼續執行程式,即可得到 flag ## Web ### 1. Ping #### 題目分析 上網搜尋一下會發現這種題形是 CTF Web 類別中最基礎的題行,概念是可以透過 command 所提供的 playload 將其他指令一起帶進去。 #### 解題過程 1. 嘗試將 `ls` 指令帶進去後看看 server 內有什麼資料 2. 可以發現 server 內有一個名為 `flag` 的資料夾 3. 再透過 `ls` 指令查看 `flag` 資料夾內的內容可以發現 `flag.txt` 4. 透過 `cat` 將 `flag.txt` 中的內容印出來即可取得 flag ### 2. EZphp #### 題目分析 題目要求我們輸入檔名,任意輸入一個不存在在 server 上的 檔名後會得到 `Warning: file_get_contents(): Filename cannot be empty in /var/www/html/index.php on line 35` ,上網搜尋 CTF php 以及 `file_get_contents()` 相關的內容會找到很多關於 php 偽協定的內容,了解偽協定的定義後,試著透過偽協定將後端執行程式 `index.php` 檔撈出來看。 #### 解題過程 1. 嘗試使用偽協定 `file:///var/www/html/index.php` 撈出 `index.php` 的內容結果失敗 2. 嘗試以偽協定的方法傳入 `php://filter/read=convert.base64-encode/resource=index.php` 給 server ,成功取得一串亂碼 3. 將此亂碼用 base64 online decoder 解碼及可以看到後端執行程式 `index.php` 的程式碼,其中 flag 就才在裡面 ```php= <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <p>Get me a file name, I'll read the file for you !</p> <p style="color:gray;"> * Try 1.txt </p> <form action="index.php" method="post"> Your input: <input type="text" name="input" /> <input type="submit" name="送出表單"/> </form> <?php // The flag for EZphp is EENS{3ccbd7b55e67a09bc085e32f6a79e2cfdfe03e8525ae2e27c92a646c679bf00c} $ip = $_SERVER["REMOTE_ADDR"]; if ($ip == '127.0.0.1'){ // EZphp_3 $content = file_get_contents("flagVGhpc0lzQUZsYWdDYW5ub3RCZUZvdW5k"); echo $content; } elseif($_SERVER["HTTP_CLIENT_IP"]=='127.0.0.1' && $_SERVER["HTTP_X_FORWARDED_FOR"] =='127.0.0.1'){ // EZphp_2 $content = file_get_contents("flagSWRvbnR3YW50eW91a25vdw=="); echo $content; } else{ $input .= $_POST [ 'input' ]; $filename = trim($input); if (strpos($input, 'flag') !== false){ echo "<br>"; echo "You are a bad hacker !!!"; } else{ $content = file_get_contents($filename); if (preg_match("/flag/i", $content)){ echo "<br>"; echo "You are a bad hacker !!!"; } else{ echo "<br>"; echo $content; } } } ?> </body> </html> ``` >參考資料 >[CG-CTF web之file_get_contents] (https://blog.csdn.net/silence1_/article/details/90241302) >[CTF-web 第八部分 常見加密與檔案包含 偽協議] (https://www.itread01.com/content/1542424327.html) >[文件包含漏洞与PHP伪协议] (https://www.smi1e.top/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E%E4%B8%8Ephp%E4%BC%AA%E5%8D%8F%E8%AE%AE/) > ### 3. EZphp_2 #### 問題解析 這題提供的 server 和上一題一樣,且從上一題拿到的 `index.php` 檔案中可以看見註解有告訴我們這一題的題目其實在 `index.php` 內。若試著將這個 case 內會開啟的檔案名 `flagSWRvbnR3YW50eW91a25vdw==` 嘗試當成輸入傳進後端,程式會偵測到該檔案內容含有 `flag` 字樣而印出 `You are a bad hacker !!!` 字眼,因此我們只能想辦法進入後端程式的第二個 `elseif` case 內,讓 server 回傳 flag 回來。上網搜尋一下會發現 `elseif` 的判斷條件是拿本地端發送出去的 `request header` 內的參數做判斷,若能透過工具攔截封包並更改 `request header` 應該就能拿到 flag。 #### 解題步驟 1. 用 Kali 上的 Burp Suite 工具建立代理伺服器並攔截封包 2. 將封包中的 `request header` 做修改,增加 `CLIENT_IP: 127.0.0.1` 和 `X_FORWARDED_FOR: 127.0.0.1` 3. 修改封包後就可以得到 flag ### 4. EZphp_3 #### 問題解析 這題一樣要從之前拿到的 `index.php` 下手,這次要想辦法進入第一個 `if` case 才能拿到 flag 。而這次的判斷式是 `$ip == '127.0.0.1'` ,也就是向 server 發 request 的 ip 要是 `127.0.0.1` 。這裡我們又可以運用 `EZphp` 學到的偽協定技術,透過 `http://` 偽協定使 server 訪問自己,也因為是 server 訪問自己,ip 就會是 `127.0.0.1` #### 解題過程 輸入 `http://127.0.0.1` 就可以拿到 flag。 ### 5. Try to login #### 問題分析 這題要我們輸入使用者的名稱以及密碼,輸入對了才能 `login` ,上網搜尋了一下相關 CTF 題目,發現一個常用的漏洞叫 `SQL Injection` ,顧名思義就是將輸入一些特殊字元如註解符號等等,改變原本程式的執行流程。 #### 解題過程 1. 猜測後端是用 SQL 語法來比對 username 以及 password 2. 將 username 比對的地方先將一個 `'` 符號,讓後端程式以為輸入字串到此結束 3. 進行 `or true` 的動作,使得判斷式不管如何都會成立 4. 加 `#` 將後面判斷式都註解掉 5. username 的輸入如下,password 責任意輸入 ``` ' or ture # ``` 6. 拿到 flag ### 6. Cookie Monster #### 問題分析 又是一個 `login` 的題目,試著按照上一題的解法卻無法成功,後端比對 `username` 和 `password` 程式碼應該有所不同。在登錄頁面使用 chrome 所提供的 debugger 能夠看到網頁 html 的 source code ,發現有一組特殊的註解,`<!-- testing account: keroro-->` 以及 `<!-- testing password: keroro123-->` ,按照提示將帳號密碼輸入進去後得到下面提示 ![](https://i.imgur.com/XzD3e4T.png) 得到上面提示後,再根據這題的題目提示,此題應該會跟 cookie 有關,再次使用 chrome 提供的功能查看 coockie 相關資訊。 #### 解題過程 使用 chrome 查看 coockie 內容時,會看到如下圖的資訊 ![](https://i.imgur.com/8IWnnAP.png) 這時會發現 `level` 那意欄的 value 目前為 `user` 狀態,將 `user` 改成提示給的 `admin` 並將網頁重新整理,使得 server 存取到 coockie 的資訊,即可拿到 flag。 ### 7. Chained Connie #### 問題分析 一樣透過 chrome 所提供的工具,觀察 `request headers` 和 `respose headers` 可以發現在 `response headers` 中有一個特殊的類別叫 `flag` ,這八成和解題有關。再仔細看一下會發現在發送 request 的時候會順代傳遞一個參數 `p` 給 server ,將 `p` 的值任意改一下,會發現收到的 `response headers` 內的 flag 值改變了,因此猜測最終的 flag 為給定不同 `p` 值後,收到的 `flag` 字元組合。 #### 解題過程 1. 先嘗試參數 `p` 的範圍,會發現 `p` 的範圍是從 `0~29` 2. 用 curl 接收從 server 拿到的封包 3. 並撰寫一個 python 程式將收到的所有封包做整理,並將所有封包內 `response headers` 的 `flag` 變數的值,全部連接在一起組成最終的 flag,程式碼與腳本如下: 腳本 ``` url=http://eens.ee.ncku.edu.tw:5103/search?p=[00-29] curl ${url} -I | grep flag >> flag.txt python3 filter.py ``` Python code ```python= import re f = open("./flag.txt").read() ans = re.findall("(flag: ([a-z]|[A-Z]|_|{|}))+", f) flag = "" for i,j in ans: flag = flag + j print(flag) ``` :::info # Resources ## CTF - [Web-CTF-Cheatsheet](https://github.com/w181496/Web-CTF-Cheatsheet/blob/master/README.md#php-webshell) ## Ping - [CTF中ping文件執行漏洞無回顯反彈拿flag](https://blog.csdn.net/qq_42877694/article/details/88928197) - [CTF關於ping命令注入問題(1)](https://www.twblogs.net/a/5c81351dbd9eee35fc137b33) - [ISITDTU CTF 2019 EasyPHP 回顾](https://blog.zeddyu.info/2019/07/20/isitdtu-2019/) :::