跳至主要内容

A03-2: XSS 注入漏洞(Injection)

漏洞概述

跨站腳本(XSS,Cross-Site Scripting)是一種網路攻擊,攻擊者在 Web 應用中注入惡意 JavaScript,使受害者的瀏覽器執行惡意代碼,可能導致竊取 Cookie、劫持會話、偽造請求等攻擊行為。

xss-attack-process


1. 反射型 XSS(Reflected XSS)

概念: 反射型 XSS 是一種發生在即時請求處理的攻擊,攻擊者透過 URL 參數、表單輸入等方式將惡意 JavaScript 注入,並讓受害者點擊惡意連結,當伺服器回應該請求時,惡意腳本被嵌入到 HTML 內並在瀏覽器執行。

攻擊流程

  1. 攻擊者構造帶有惡意 JavaScript 的 URL,誘導使用者點擊。
  2. 伺服器未進行適當的過濾或轉義,直接回傳用戶輸入的內容。
  3. 使用者瀏覽器執行這段惡意 JavaScript,導致 XSS 攻擊。

❌ 有漏洞的程式

package main

import (
"fmt"
"html/template"
"net/http"
)

func main() {
http.HandleFunc("/", xssHandler)
http.ListenAndServe(":8080", nil)
}

func xssHandler(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("input")

// 這裡沒有做適當的輸入過濾,直接輸出用戶輸入內容,可能導致 XSS
htmlContent := fmt.Sprintf(`<html><body>你的輸入: %s</body></html>`, query)
w.Write([]byte(htmlContent))
}

🔍 檢測方法

  1. 使用 ZAP 檢測出有 XSS 的漏洞。

zap-reflacted-xss

  1. 使用 dalfox 檢測,
dalfox url "http://192.168.56.1:8080/?input=123"

輸出的結果為:

[V] Triggered XSS Payload (found DOM Object): input=<ScRipt class=dalfox>prompt.valueOf()(1)</script>
1 line: dy>你的輸入: 123<ScRipt class=dalfox>prompt.valueOf()(1)</script></body></ht
[POC][V][GET][inHTML-none(1)-URL] http://192.168.56.1:8080/?input=123%3CScRipt+class%3Ddalfox%3Eprompt.valueOf%28%29%281%29%3C%2Fscript%3E

✅ 修正方式

使用 html/template 套件來避免 XSS:

tmpl := template.Must(template.New("page").Parse(`<html><body>你的輸入: {{.}}</body></html>`))
tmpl.Execute(w, query)

2. DOM 型 XSS

概念: DOM 型 XSS 發生在用戶端,瀏覽器內的 JavaScript 直接操作 DOM 並執行惡意腳本,而不經過伺服器處理。

攻擊流程

  1. 攻擊者構造惡意的 URL,如:
    http://example.com/page?name=<script>alert('XSS')</script>
  2. 瀏覽器 JavaScript 解析 URL 並修改 DOM,導致惡意腳本執行。

❌ 有漏洞的程式

package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/", domXSSHandler)
http.ListenAndServe(":8080", nil)
}

func domXSSHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name") // 直接取得 name 參數,未進行任何過濾

// 將用戶輸入的內容直接插入 HTML(這樣可以成功執行 XSS)
htmlContent := fmt.Sprintf(`
<html>
<body>
<p>輸入你的名稱:</p>
<input id="nameInput" type="text">
<button onclick="showName()">提交</button>
<p id="output">%s</p> <!-- 直接插入未過濾的輸入 -->
<script>
function getQueryParam(param) {
let params = new URLSearchParams(window.location.search);
return params.get(param);
}
function showName() {
document.getElementById("output").innerHTML = getQueryParam("name");
}
</script>
</body>
</html>`, name) // 這裡直接插入 name,會導致 XSS

w.Write([]byte(htmlContent))
}

🔍 檢測方法

  1. 使用 ZAP 檢測出有 XSS 的漏洞。

zap-dom-xss

  1. 使用 dalfox 檢測,並且加上--deep-domxss可以更深入找尋 DOM-XSS 的漏洞。
dalfox url "http://192.168.56.1:8080" --deep-domxss

輸出的結果為:

[V] Triggered XSS Payload (found DOM Object): name=<iframe srcdoc="<input onauxclick=alert(1)>" class=dalfox></iframe>
7 line: <p id="output"><iframe srcdoc="<input onauxclick=alert(1)>" class=dalfox></i
[POC][V][GET][inHTML-none(1)-URL] http://192.168.56.1:8080?name=%3Ciframe+srcdoc%3D%22%3Cinput+onauxclick%3Dalert%281%29%3E%22+class%3Ddalfox%3E%3C%2Fiframe%3E

✅ 修正方式

使用 textContent 來避免 HTML 解析:

document.getElementById('output').textContent = getQueryParam('name');

3. 儲存型 XSS(Stored XSS)

概念: 儲存型 XSS 是將惡意 JavaScript 存入伺服器的資料庫,當其他使用者讀取該資料時,惡意腳本在瀏覽器執行。

攻擊流程

  1. 攻擊者提交惡意腳本,例如:
    <script>
    alert('XSS!');
    </script>
    這段 JavaScript 被儲存到伺服器的資料庫中。
  2. 當其他用戶存取該頁面時,伺服器讀取資料並返回 HTML,導致惡意腳本執行。

❌ 有漏洞的程式

package main

import (
"fmt"
"net/http"
"sync"
)

var (
messages []string
mu sync.Mutex
)

func main() {
http.HandleFunc("/", formHandler)
http.HandleFunc("/submit", submitHandler)
http.ListenAndServe(":8080", nil)
}

func formHandler(w http.ResponseWriter, r *http.Request) {
// 直接使用 fmt.Sprintf 生成 HTML,不使用 html/template 來防止自動轉義
htmlContent := `
<html>
<body>
<form action="/submit" method="POST">
<input type="text" name="message">
<button type="submit">送出</button>
</form>
<h2>留言列表:</h2>
<ul>`

// 這裡直接插入 messages,會讓 script 被執行
mu.Lock()
for _, msg := range messages {
htmlContent += fmt.Sprintf("<li>%s</li>", msg)
}
mu.Unlock()

htmlContent += `
</ul>
</body>
</html>`

w.Write([]byte(htmlContent))
}

func submitHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
r.ParseForm()
message := r.FormValue("message")

mu.Lock()
messages = append(messages, message) // 直接儲存用戶輸入(無過濾)
mu.Unlock()

http.Redirect(w, r, "/", http.StatusSeeOther)
}
}

🔍 檢測方法

  1. 使用 dalfox 檢測,並起提供攻擊點和傳入的 id,並指示為 POST,就能發現 XSS 問題。
dalfox url "http://192.168.56.1:8080/submit" -d "message=<script>alert('XSS')</script>" --method POST

輸出的結果為:

[V] Triggered XSS Payload (found DOM Object): show=<ScRipt class=dalfox>alert(1)</script>
[POC][V][POST][inHTML-none(1)-FORM] http://192.168.56.1:8080/submit -d message=%3Cscript%3Ealert%28%27XSS%27%29%3C%2Fscript%3E&show=%253C%2553%2563%2552%2569%2570%2574%2520%2563%256C%2561%2573%2573%253D%2564%2561%256C%2566%256F%2578%253E%2561%256C%2565%2572%2574%2528%2531%2529%253C%252F%2573%2563%2572%2569%2570%2574%253E

✅ 修正方式

submitHandler 使用 html.EscapeString 來過濾輸入:

message := html.EscapeString(r.FormValue("message"))

🔍 Dalfox 檢測工具

Dalfox(DalPoong XSS)是一款功能強大的 XSS(跨站腳本攻擊)漏洞掃描工具,由韓國安全研究員 hahwul 開發。它基於 Go 語言,主要用於自動化檢測和利用 DOM-based XSS、Reflected XSS、Stored XSS 等漏洞,適用於滲透測試人員和安全研究者。

特色功能

  1. 多種掃描模式
    • URL 掃描:提供單個 URL 探測
    • 參數掃描:針對特定參數進行 XSS 測試
    • 自動爬取:可以自動探索網站內部的鏈接和輸入點
    • Header 注入:檢測 RefererUser-Agent 等標頭是否可被利用
  2. 高效能
    • 基於 Go 語言,執行速度快
    • 多執行緒,可同時測試多個目標
  3. 豐富的 Payload
    • 預設內建 多種 XSS Payload
    • 自動編碼(如 HTML 實體、Base64 等)
    • 自定義 Payloads,適應不同環境
  4. 支持外部工具
    • 可以與 Burp Suite、SQLmap、Metasploit 等安全工具結合使用
  5. API & 自動化
    • 可透過 CLI(命令行) 操作,適合整合到 DevSecOps 工作流程
    • 提供 JSON 輸出,方便分析和自動化測試

安裝方式

前提條件:需要安裝 Go(>=1.14)

go install github.com/hahwul/dalfox/v2@latest

或使用 Docker

docker pull hahwul/dalfox
docker run -it hahwul/dalfox

基本用法

  1. 掃描單個 URL
dalfox url "http://example.com/?q=hello"
  1. 掃描包含多個 URL 的文件
dalfox file target_list.txt
  1. 與 Burp Suite Proxy 結合
dalfox proxy -b "http://127.0.0.1:8080"
  1. API 模式
dalfox server --port 8080

官方資源


結論

XSS 是網頁應用程式常見的安全漏洞,分為:

  1. 反射型 XSS:透過 URL 觸發,影響單次請求。
  2. DOM 型 XSS:JavaScript 操作 DOM 而導致的攻擊。
  3. 儲存型 XSS:惡意腳本儲存於伺服器,影響後續用戶。