Juice Shop Write-up (整理過後版)
===
---
###### tags: `JuiceShop` `CTF` `security` `Web`
依照題目類型整理
有些 Write-up 或許可能Maybe會有先後順序的問題
所以我依舊會優先更新流水帳版本的 write-up 再更新這篇
流水帳版本 Write-up: https://hackmd.io/@LJP/HktxnOpR4
---
[TOC]
# XSS
## XSS Tier 0
```
<iframe src="javascript:alert(`xss`)">
```
以上打在 Track Orders 中

## XSS Tier 1
```
<iframe src="javascript:alert(`xss`)">
```
以上打在 Search 中

## XSS Tier 1.5
Set Username 中有套某些 RegEx,導致某種長相的字串會被取代
中間不小心試到一個 整個爆掉 = =

中間嘗試了很多 pattern
以下列著比較有意義的嘗試
| Before | After
| -------- | -------- |
| `<script>alert(`\``xss`\``)</script>` | `lert(xss)</script>` |
| `<</abcd>/abcd>` | `</abcd>` |
| `<<abcd>efgh>` | `<fgh>` |
| `<<a>efgh>` | `<fgh>` |
| `<<a>ascript>` | 頁面炸裂,`<script>` |
| `<<a>ascript></script>` | `<script></script>` |
| `<<a>ascript>alert(`\``xss`\``)</script>` | `<script>alert(`\``xss`\``)</script>` |
用最後一筆 pattern 就成功囉~
## XSS Tier 2
> Perform a persisted XSS attack with \<iframe src="javascript:alert(\`xss\`)"\> bypassing a client-side security mechanism.
persisted 的欄位,一開始直覺就是商品底下的 comment,但是踹 comment 沒有成功
回頭想想 persisted 的欄位、其他 User 看得到的,
J個嘛......
腦筋動到 User 本身上
- ~~User 名稱~~ (只能在自己的帳號管理頁面看到)
- User Email (admin 在主控台看得到,在 comment 中也會顯示)
User 名稱踹踹看,繼承 XSS Tier 1.5 嘗試中有些 RegEx 要閃
```
<<a>aiframe src="javascript:alert(`xss`)">
```
WoW

(噢對了 我頭像有亂改過)
然後玩到這裡才突然想到,comment 中顯示的不是 Username 而是 email
果斷放棄改 Username
改踹 Email,可是 Email 在註冊時就決定了,所以只能踩看看註冊API了
不過這次硬把 Register Button Enable 起來,也送不出 Request
好吧,只好攔截爆改了
把 Email 改成
```
<iframe src='javascript:alert(`xss`)'>
```


唉呦 可以ㄛ
試試看登入,發現糗了

登不進啦乾
but 還可以從 admin 頁面看到這個 email

一進來就 xss,表示真的成功了

阿可是這題沒解開,該不會是一定要打以下吧?
```
<iframe src="javascript:alert(`xss`)">
```
沒關係就來試試看
因為參數結構是
```
"email":"<blablabla...>"
```
要閃雙引號,所以改成如下

欸,一送出去,連驗證 xss 有沒有成功都不用就解這題了

# Broken Access Control
## Five-Star Feedback
進入 administration 後
砍掉五星評價
over
## Basket Access Tier 1
觀察按下去 Your Basket 後會發送什麼封包


看到 Request URL: `http://192.168.124.141:3000/rest/basket/3`
3 是我現在登入的帳號的編號
很好,直接用 burpsuite 改改看那個數字

改成 4 看看
就拿到帳號編號為 4 的 basket 了
以下這張為沒有竄改封包 本人的basket

以下這張為帳號編號為 4 的 basket

也解這題了
## Admin Section
用 `admin@juice-sh.op' -- ` 登入後
再進 administration
就解這題了

## Forged Review
既然 basket 都能亂存取到其他帳號的 basket
那麼其他功能是否也能亂存取到其他帳號的呢 e.g. 留言 按讚 結帳
留言的更改 是打以下 request:

Method 為 PATCH
API 在 /rest/product/reviews
id 推測為該留言的 id, message 為更改的內容
馬上來試改其他留言看看
先來查看隨便其中一個 product 的 review

得到id,來改看看封包,先編輯自己的留言,並用burpsuite攔截下來

把id改掉

成功爆改並解題

cool
## Forged Feedback
主要是這個頁面

用 Network 看了一下執行流程
1. 先 GET http://192.168.124.137:3000/rest/captcha/
取得一筆 json
內容為 answer, captcha, captchaId

2. POST 到 http://192.168.124.137:3000/api/Feedbacks/
POST 的欄位分別為 captcha, captchaId, comment, rating

寫了個 python 壓力測試
```python=
import requests
import json
host = "192.168.124.137:3000"
captcha_url = "http://" + host + "/rest/captcha/"
feedback_url = "http://" + host + "/api/Feedbacks/"
for i in range(50):
resp = requests.get(captcha_url)
data = resp.json()
postdata = {'UserId': 1,
'captcha': str(data['answer']),
'captchaId': data['captchaId'],
'comment': "YEEEEE",
'rating': 0
}
r = requests.post(feedback_url, data = postdata)
```
就解ㄌ
## Basket Access Tier 2
我在想能不能隨便幫其他 user 亂加東西到購物車
首先,先觀察加進購物車的流程


看來關鍵是這個API:
POST `http://192.168.124.141:3000/api/BasketItems/`
BasketId 為要加進的 Basket
ProductId 為產品
quantity 為數量
好像很簡單 馬上攔截下來爆改看看


欸欸欸 無效 BasketId ?
那我改成登入 admin,然後硬給 BasketId 3 加咚咚試試看

結果還是一樣
那還是我刻意忽視掉的 API:

GET `http://192.168.124.141:3000/rest/basket/1`
是有作用的?
就是其實他有先打 GET rest/basket/{BasketId} (或有可能是 UserId)
再打 POST api/BasketItems
這次爆改 要連第一個GET都不放過試試看
登入admin,亂加購物車,攔截下來改:

結果一樣不行
那會不會是,真的有判斷登入者是誰?
不過經過一番研究後
發現 如果我的 basket 中已經有一個商品
再按一次加入購物車 會呼叫這個 API

這個商品在我的購物車中 原先已經有了10個
感覺是JS運算給他 +1 並打這個 Request 過去修改數量
我先測試看看 這個數量是否是能修改的


OK 看來後端沒檢查值一定要是剛好 +1 過後的
這個API是這樣
PUT `http://192.168.124.141:3000/api/BasketItems/8`
quantity 是數量
網址列中 最後的數字 8 應該是指 BasketItemId
已知 id = 8 的 BasketItem 是屬於 admin 的
現在就來登入其他帳號,並且試著透過這個API來修改這 id = 8 的 BasketItem 的 quantity
原先封包

改成

好像修改成功了


BananaJuice 變 50 個啦
但我終極目的是要幫其他 user 亂加東西進購物車餒
我在想 打 POST api/BasketItems 這API
我竄改後,他Response是401
真的要登入的話 就要幹 cookie 或是 session
~~好麻煩~~
最後放棄 Google 了 Write-up
看到結果後 還好我放棄了

原來有這種東西 長知識了!
馬上來玩玩看

Response:

成功把它加進其他user的購物車!!!
太神啦!!!
成功解掉這題
cool
# Injection
## Login Admin
再回來看看登入介面 嘗試看看 SQL Injection

回傳了...

所以若我知道 admin 的信箱是啥
而且輸入的部分沒有檔 '--' 或 '#'
就可以直接 injection 登進去
就先用看看
`' or 1=1 --`
就登入進去了
## Login Jim
用 `jim@juice-sh.op' -- ` 登入就解了 over
## Login Bender
用 `bender@juice-sh.op' -- ` 登入就解了 over
# Race Condition
# Insecure Deserialization
# Vulnerable Components
# Sensitive Data Exposure
## Confidential Document
進去 About Us 後,看到一個
Check out our boring terms blablabla....

進去後是長這樣

看看目錄有沒有設定讀取保護

耶 看來是沒有 ㄎㄎ

可是有保護說副檔名要是 .md 或 .pdf
就先踩踩這個 md ㄅ

就又解一題了 (????
## Weird Crypto
這題題目寫說,透過 Contact Us 告訴 Server 一個被誤用的 Algorithm 或 Library
我是回傳 md5,不過理由是 logout 那邊會用 md5 hash 密碼並傳回來,而這件事情不應該發生
官方 write-up 對於 md5 是個答案的原因這樣寫:
> Passwords in the Users table are hashed with unsalted MD5
>
我的理解是,密碼以 unsalted MD5 hash 過再存回資料庫,但照理說應該要加一些料,讓他不是單純的 MD5
不過以黑箱的角度,能觀察到這件事情嗎?
除非我能 SQL Injection 直接 dump 整個 database 出來看,才能知道這件事吧
但其實不用,在登入頁面時,觸發 SQL 錯誤,會回傳整個 SQL Statement

那個 password 可以自行驗證一下,的確只是 md5 hash 過而已
得證資料庫中,Table Users 中的 password 為 unsalted md5 hash
## Login MC SafeSearch
這題看了一下提示,聽了一下
先登入了 admin 看了一下 email 是 `mc.safesearch@juice-sh.op`
再來登看看就登入ㄌ
# Security Misconfiguration
## Error Handling
不知道怎樣 莫名其妙解了 好像是隨便造成 server 的 error 都可解這題
我是有亂踩 SQL Injection 測試
## Forgotten Sales Backup
同 Easter Egg Tier 1
# Broken Authentication
## Password Strength
研究一下 logout
API:

Return:

其中密碼是32個16進制組成的
讓人聯想到,是否原本密碼會以某種 128bits(32 * 4) 加密法加工並且回傳
若以未登入之姿進入這個API

嗯,沒搞頭。
在其他題時就已經能登入 admin 了
看看 admin 登出後,那個看似 hash/encrypt 過的密碼長怎樣

```
email admin@juice-sh.op
password 0192023a7bbd73250516f069df18b500
```
128bits hash algorithms 有 MD5
測試看看線上破解網站

well 一個弱密碼
`admin123`
用原本的帳密登入 就解這題了
# Security through Obscurity
## Score Board
在一開始 Load 網頁時就監控 Network

發現有一個特別牛逼

看看內容是什麼

後來閒閒沒事又把其他咚咚看了

看得了關鍵的 URL: /#/score-board
連進去看看 就解開這題了
## Easter Egg Tier 2
繼承 Easter Egg Tier 1
當時是猜用凱薩密碼加密
用網站 brute-force 了一下

```
/gur/qrif/ner/fb/shaal/gurl/uvq/na/rnfgre/rtt/jvguva/gur/rnfgre/rtt
/THE/DEVS/ARE/SO/FUNNY/THEY/HID/AN/EASTER/EGG/WITHIN/THE/EASTER/EGG
```
該不會這是一個路徑吧

**WOW靠!! 是怎樣 這星球還會動**
造訪了這顆星球後,這題就解了
# XXE
# Forgotten Content
# Roll your own Security
## Privacy Policy Tier 1
privacy-security 頁面進去就解這題了

## CAPTCHA Bypass Tier 1
Forged Feedback的解法 可以一起把這題解掉
## Forgotten Developer Backup
ㄜ 我想故技重施(參見 Easter Egg Tier 1) 把整個 FTP 看到的都載下來 就也解這題ㄌ
## Easter Egg Tier 1
繼承上面
結果不知道為啥 incident-support.kdbx 可以下載!???!?

注意下方 我把它 download 下來了
用 notepad++ 開

well, 我還是用 binwalk 看看他是啥好了

結果啥都不是@@
好不重要,重要的是,我知道還是有辦法下載下來的
但後來餵狗後 發現我思考方式好像錯了
原本我想說 找找 GET .kdbx 與 GET 其他檔案 打的封包有什麼不同
後來發現更牛逼的方式

用 Burpsuit 攔截封包

把第一行的 GET 改成
```
GET /ftp/eastere.gg%00.md HTTP/1.1
```
看看
欸豆 不行

後來再查了一下,發現連 % 都要用URL Encoding
所以 % 要改成 %25

耶~~ 下載下來ㄌ
內容長醬子

那個一臉 Base64 樣的字串
```
L2d1ci9xcmlmL25lci9mYi9zaGFhbC9ndXJsL3V2cS9uYS9ybmZncmUvcnR0L2p2Z3V2YS9ndXIvcm5mZ3JlL3J0dA==
```
解碼後變成
```
/gur/qrif/ner/fb/shaal/gurl/uvq/na/rnfgre/rtt/jvguva/gur/rnfgre/rtt
```
欸先等等 已經解一題了 (不得不說 解題解的莫名其妙的
先記一下感覺,這解碼後的東東,可能可以試試看凱薩
## Misplaced Signature File
同 Easter Egg Tier 1
# Improper Input Validation
## Zero Stars
硬把 Submit button 的 disable 取消
就可以發送 0 星評價ㄌ
## Repetitive Registration

砍掉 disable

來送一個 `password` 跟 `passwordRepeat` 欄位不一樣的 Request 試試看

可以註冊,表示重複密碼這件事情只有在前端有檢查,後端卻沒擋掉。