iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
Build on Google AI

30 天打造 AI Web Security Agent:從 Google AI Studio 到 Gemini Agent系列 第 6 篇

Day 6|如果AI用來整理報告,那製作出來的工具能測到漏洞嗎

  • 分享至 

  • xImage
  •  

前言

昨天整理 XSS 的形成過程時,我把判斷拆成幾個階段:找到輸入點、追蹤輸入、分析輸出位置,最後才是驗證瀏覽器行為。

如果工具只看到輸入出現在回應中,最多只能證明「發生反射」;即使輸入成為新的 HTML 元素,也還沒有證明 JavaScript 能夠執行。

所以今天,來測試看看自己能不能跟AI一起做出一個基本的工具

今天要驗證什麼?

我希望工具能區分 3 種情況:

情況 工具要看到的證據
JavaScript 實際執行 執行後 DOM 出現本次探針寫入的唯一識別碼
輸入被反射,但沒有執行 回應中有識別碼,執行後 DOM 沒有旗標
輸入沒有被反射 回應與執行後 DOM 都找不到本次識別碼

第一種情況同時包含輸入、瀏覽器執行與可核對的結果,才足以在這個固定測試案例中標為 confirmed_xss。

直接使用 alert(1),但讓工具自動處理

常見的 XSS 示範會使用 alert(1)。既然今天操作的是自己建立的本機環境,我就直接使用它,讓執行結果保持直觀。

為了確認這個對話框確實來自本次探針,我也保留唯一識別碼。圖片載入失敗時,事件處理器會先在 <html> 寫入識別碼,再呼叫 alert(1):

<img
  src="/day6-missing.png"
  onerror="document.documentElement.setAttribute(
    'data-day6-xss',
    'owo'
  ); alert(1)"
>

如果這段程式成功執行,瀏覽器中的 <html> 會變成:

<html lang="zh-Hant" data-day6-xss="owo">

探針不會讀取 Cookie、不會傳送資料,也不會修改網站狀態。除了顯示 alert(1),它只留下本次測試的執行旗標,方便程式核對。

先建立 3 個本機對照頁面

為了讓結果可以重現,我建立了一個只在 127.0.0.1 上執行的測試網站,並準備 3 個端點。

弱點示範頁直接把 q 放進 HTML:

body = PAGE.format(title="弱點示範頁", value=value)

安全示範頁先做 HTML 編碼:

body = PAGE.format(title="安全示範頁", value=html.escape(value))

第三個頁面則完全不顯示 q,用來確認工具不會在沒有反射時回報相同結果。

這些頁面都是刻意建立的本地環境。偵測器也只接受 localhost、127.0.0.1 與 ::1,不會把初版實驗送到外部網站。

偵測器怎麼判斷?

執行流程可以整理成:

產生owo
        ↓
把測試探針放進 q 參數
        ↓
保存伺服器的原始 HTML 回應
        ↓
以無頭模式的 Chrome 載入相同網址
        ↓
捕捉並關閉內容為 1 的 alert
        ↓
核對 data-day6-xss 是否也等於本次識別碼

工具先保存原始回應,再啟動獨立的暫存瀏覽器設定檔。接著透過 Chrome DevTools Protocol 監聽 Page.javascriptDialogOpening 事件。

捕捉到對話框後,工具會保存類型與訊息,然後送出關閉對話框的指令:

if message.get("method") == "Page.javascriptDialogOpening":
    params = message.get("params", {})
    dialog_type = params.get("type")
    dialog_message = params.get("message")
    send("Page.handleJavaScriptDialog", {"accept": True})

頁面載入完成後,工具再讀取 data-day6-xss。只有對話框類型是 alert、訊息是 1,而且 DOM 識別碼也與本次探針相同時,才輸出 confirmed_xss。如果輸入能建立元素,卻沒有完整執行證據,就輸出 html_injection_only;有反射但沒有建立元素與執行時,則輸出 reflected_but_not_executed。

實際執行

我先啟動本機測試網站:

python3 day-06/lab_server.py

接著分別測試 3 個端點:

python3 day-06/xss_detector.py http://127.0.0.1:8000/vulnerable
python3 day-06/xss_detector.py http://127.0.0.1:8000/safe
python3 day-06/xss_detector.py http://127.0.0.1:8000/not-reflected

實際結果如下:

端點 工具分類 alert_observed execution_observed
/vulnerable confirmed_xss true,訊息為 1 true
/safe reflected_but_not_executed false false
/not-reflected not_reflected false false

3 次請求都收到 200 與 text/html 回應,分類符合預期。

弱點頁先觸發內容為 1 的 alert。工具將它關閉後,也從瀏覽器讀到:

<html lang="zh-Hant" data-day6-xss="owo">

這個屬性不存在於伺服器原始頁面,只能由探針中的 JavaScript 寫入。alert(1) 事件與唯一 DOM 識別碼同時成立,讓工具不必只依賴其中一種訊號。

安全頁雖然也在回應中保留識別碼,但標記已經變成文字:

&lt;img src=&quot;/day6-missing.png&quot; ... &gt;

Chrome 不會把它建立成圖片元素,onerror 也不會執行。這個對照說明「輸入出現在回應中」與「程式真的執行」是兩件不同的事。

加上自動測試

除了分別執行 3 次,我也加入 5 個自動測試,檢查弱點頁、安全頁、不反射頁面、原有查詢參數,以及外部網址限制。

python3 -m unittest discover -s day-06 -p 'test_*.py' -v

測試會真的啟動 Chrome,而不是模擬瀏覽器結果。這次 5 個測試全部通過,其中弱點頁的測試同時核對:

  • 分類是 confirmed_xss。
  • alert_observed 是 true。
  • dialog_message 是 1。
  • execution_observed 是 true。
  • dom_marker 是正確的本次識別碼。

我預計把 AI 放在哪裡?

是否執行成功,可以由瀏覽器對話框事件與 DOM 旗標共同判斷,不需要請模型猜測。

後續接回 AI Web Security Agent 時,我希望 AI 負責整合原始回應、HTML 結構、alert 事件、DOM 識別碼與限制,並轉成容易閱讀的報告。底層工具仍要保留這些原始證據,讓每個結論都能回頭核對。

這樣的分工延續前幾天的原則:先取得可重現的證據,再讓 AI 協助分析。

今天的進度

今天,我完成了第一個能實際驗證 XSS 執行的工具。它會送出包含 alert(1) 的唯一探針、保存原始回應、啟動 Chrome、捕捉並關閉對話框,最後再讀回 DOM 旗標。

在弱點頁中,JavaScript 確實觸發 alert(1),因此工具能把結果標為 confirmed_xss;安全頁與不反射頁則沒有出現對話框或執行旗標。

接下來,我會逐步加入不同的輸出情境,避免工具只能辨認這一種固定的 HTML 文字位置。

那就…
明天見!


上一篇
Day 5|工具要找什麼?XSS篇
下一篇
Day 7|把昨天的 XSS 工具接上 AI:讓它分析風險,但不能改寫證據
系列文
30 天打造 AI Web Security Agent:從 Google AI Studio 到 Gemini Agent 共 12 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言